C #: универсальные унаследованные фабрики - PullRequest
3 голосов
/ 21 февраля 2011

У меня есть базовый класс, который принимает один общий аргумент.Затем у меня есть несколько классов, которые наследуются от этого базового класса.Есть ли простой способ для дочерних классов встроить фабрику из базового класса?

Пример

class BaseClass<T>
{
     T Value {get; set;}
     string Name {get; set;}

     public static BaseClass<T> Factory(T Value)
     {
        return new BaseClass<T>(Value); 
     }
}

class ChildClass : BaseClass<int>
{
     public void Test()
     {
         // I want this below to work
         // but Factory() returns a BaseClass
         ChildClass bs = ChildClass.Factory(10);
     }
}

Я отметил в коде, что я хочу работать.Я могу придумать один способ преодолеть это, добавив неявный оператор либо в BaseClass, либо в SubClass, который преобразует из BaseClass в ChildClass.

Я также могу просто явно добавить Factory в ChildClass, но это лишает возможности наследования.

Есть ли лучший, более стандартизированный способ сделать это?

Ответы [ 2 ]

8 голосов
/ 21 февраля 2011

Я бы сделал что-то вроде этого:

class BaseClass<T, K> where K : BaseClass<T, K>, new()
{
    T Value { get; set; }
    string Name { get; set; }

    public static K Factory(T value)
    {
        return new K { Value = value };
    }
}

class ChildClass : BaseClass<int, ChildClass>
{
    public void Test()
    {
        ChildClass cs = Factory(10);
    }
}
0 голосов
/ 21 февраля 2011

Сложно ответить на ваш вопрос, поскольку вы описали, что вы пытаетесь сделать, но не почему.Поэтому я должен попытаться угадать, что вы хотите.

Я бы не поместил фабричный метод в тот же класс, что и в другом ответе или вашем вопросе.Как бы вы справились с наследованием за один раз?Это работает для двух уровней, которые у вас есть.Но что, если вы хотите расширить ChildClass?

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

class MyFactory
{
    private static IMyFactory _instance;
    public static void Assign(IMyFactory factory) { _instance = factory; }
    public static T Create<T>() { return _instance.Create<T>(); }
}

interface IMyFactory
{
    T Create<T>();
}
class MyFactoryImp : IMyFactory
{
    //do whatever needed in here
    public T Create<T>(){ return new T(); }
}


class BaseClass<T>
{
     T Value {get; set;}
     string Name {get; set;}
}

class ChildClass : BaseClass<int>
{
     public void Test()
     {
         ChildClass bs = MyFactory.Create<ChildClass>(10);
     }
}

// start with this, you can easily switch implementation
MyFactory.Assign(new MyFactoryImp());

Другой очевидный ответ - начать использовать контейнер Inversion Of Control, например, autofac.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...