C #, абстрактный суперкласс, реализующий конкретную переменную, определенную подклассом? - PullRequest
4 голосов
/ 27 февраля 2012

У меня есть система, которая выполняет операции с большим количеством Things, их можно считать аппаратными устройствами, доступными по каналу связи.

Я использую конструкцию менеджера, которая принимает задачи для одного Things. Теперь существует как минимум три типа Thing, и с ними связаны немного другие свойства. Менеджер должен знать об этих дополнительных свойствах, так как они необходимы для правильного выполнения любой операции (некоторые Things должны иметь свои X foo'd вместо своих Y и т. Д ...).

На данный момент у меня есть отдельный класс менеджера для каждого типа вещей. Это вызывает многократное дублирование, поскольку Things в основном похожи.

Было бы хорошо, если бы у меня был абстрактный менеджер, который реализует большую часть функциональности, и тогда каждая конкретная реализация может предоставить небольшие дополнительные биты.

Вот очень упрощенный пример:

public abstract class ThingManager
{
    private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;

    public virtual AddNewThingTask(<params>)
    {
        ??ThingTask?? NewTask = new ??ThingTask??(<params>);
        _ThingTaskQueue.Add(NewTask);
        Monitor.Pulse(_NewDataToProcess);
    }

    /* Implemented by the concrete, will depend on the type of ??ThingTask?? */
    public abstract GetSomeTaskParameterForAThing(Guid thingID)   
}

public class ThingTask
{
    public enum ThingOperation
    {
        Foo,
        Bar 
    };

    public String Name { get; set; };
    public ThingType Type { get; set; };
    public ThingOperation Operation { get; set; } 
}

public class AdvancedThingTask
{
    public enum ThingOperation
    {
        Foo,
        Bar,
        Baz 
    };

    public String Name { get; set; };
    public ThingType Type { get; set; };
    public ThingOperation Operation { get; set; }
    public Boolean EnableFrobber { get; set; } 
}

Как видите, мне нужен какой-то способ, при определении бетона ThingManager, чтобы ??ThingTask?? был либо ThingTask, либо AdvancedThingTask. Тогда бы было конкретное использование дополнительных свойств при реализации абстрактных методов.

Использование интерфейса для ??ThingTask?? не сработает, потому что свойства должны быть объявлены в интерфейсе, и у каждого есть разные доступные свойства.

У меня такое чувство, что я упускаю что-то очень очевидное в том, как сделать это чисто, надеюсь, кто-то может помочь:)

Ответы [ 2 ]

3 голосов
/ 27 февраля 2012

используйте дженерики, а не чистый абстрактный класс, что-то вроде:

public abstract class ThingManager<T> where T : ThingTask

зависит от вашей полной реализации Я сомневаюсь, что это нужно будет оставить абстрактным

0 голосов
/ 27 февраля 2012

Есть ли причина, по которой вы не делаете AdvancedThingTask подклассом ThingTask?

public class ThingTask
{
  public virtual string Name { get; set; }
  public virtual ThingType Type { get; set; }
  public virtual ThingOperation Operation { get; set; }

  public virtual void DoThing() { /*Do something associated with ThingTask*/ }
}

public class AdvancedThingTask : ThingTask
{
  public bool EnableFrobber { get; set; }

  public override void DoThing() { /*Do something associated with AdvancedThingTask*/ }
}

Единственная проблема, с которой я сталкиваюсь, заключается в том, что ThingOperation необходимо будет объявить вне классов, чтобы он могиметь все значения или другое решение, которое позволит классам иметь значения, которых нет в базовом объявлении.Эту проблему можно решить, поместив в класс то, что вы хотите сделать как виртуальные методы.

PS Почему ваши свойства начинаются с подчеркиваний?Обычно это зарезервировано для приватных переменных.

...