Реализация абстрактной фабрики из Actionscript в C # - PullRequest
1 голос
/ 25 января 2012

У меня есть этот абстрактный шаблон фабрики, который я использую в as3, к которому я довольно привык, и я пытаюсь реализовать его в C #, но мне не хватает знаний, вот как это происходит.

    public class Factory{

        static public ID_LOGIC_CLASS:int = AddClassLink(MyLogicClass);

        static private classLib:Array;

        public Factory(){
            classLib = new Array();
        }


        static public AddClassLink(logicClass:Class):int {
             classLib.push(logicClass);
             return classLib.length-1;
        }

        static public CreateClassFromId(int id, 
                                  constructorData:DataObject):FactoryObject{
             var c:Class = classLib[id];
             var obj:FactoryObject = new c();
             obj.Init(constructorData);
             return obj;
        }
    }

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

Единственное, чего мне не хватает, так это того, как составить список объектов классов в C # и как создатьновый объект этого класса со ссылкой на тип класса.

Я думаю, что это можно сделать с помощью конструкторов делегатов.

Скажите, что вы думаете.

1 Ответ

2 голосов
/ 25 января 2012

Вот дословный порт:

      // Untested code
public class Factory
{
    private static int _id = 0;

    // Use Dictionary to store the mapping from int to Type
    // instead of ActionScript "classLib = new Array();"
    private static readonly IDictionary<int, Type> _typeMappings = new Dictionary<int, Type>();

    public Factory()
    {
    }

    public static int AddClassLink(Type type)
    {
        // To insure uniqueness, increment a static local id and use that
        int localId = ++_id;

        // Store the Type of the class to instantiate against the integer ID
        // Similar to ActionScript "classLib.push(logicClass); "
        _typeMappings[localId] = type;          // Set in dictionary
        return localId;
    }

    pubilc static FactoryObject CreateClassFromId(int id, DataObject constructorDataObject)
    {
        // Get the class type by integer Id. 
        // You can also use _typeMappings.Contains and _typeMappings.TryGetValue() to 
        // add some checking first
        var type = _typeMappings[id];

        // This is equivalent to new DerivedFactoryObject() where Type
        // is the runtime Type of the class registered in AddClassLink
        var obj = (FactoryObject)Activator.CreateInstance(type);

        // Initialise and return 
        obj.Init(constructorDataObject);
        return obj;
    }
}

В этом примере я использовал Dictionary<TKey, TValue вместо Array, чтобы при удалении из словаря типов не возвращался идентификатор, который вы возвращаете. В приведенном выше примере, пока AddClassLink не вызывается в нескольких потоках, вы будете каждый раз получать уникальный идентификатор, даже если классы отменены.

Что касается создания экземпляра типа, используйте перегрузку System.Type, равную Activator.CreateInstance. Это может создать объект только по типу времени выполнения.

Что касается использования этого класса, если у вас есть класс, который вы хотите зарегистрировать в нем, вы бы использовали эту запись

var myFactory = new Factory();
int id = myFactory.AddClassLink(typeof(SomeClassIWantInstantiated))
// ... 
SomeClassIWantInstantiated instance = myFactory.CreateClassFromId(id, new DataObject())

Вышеуказанное должно работать (Отказ от ответственности: не проверено!) и должно быть точным портом вашего кода ActionScript. * Это не значит, что это хорошая идея или лучшие практики! *

Я рекомендую взглянуть на контейнеры Dependency Injection и взглянуть на Factory Pattern в .NET , поскольку сила отражения, типизация во время выполнения и т. Д. Позволяют реализовать этот шаблон элегантно и надежно в C #. В частности, DI Containers позволит вам зарегистрироваться и разрешить класс следующим образом

var myFactory = new DependencyInjectionContainerTm();
myFactory.Register(typeof(SomeClassIWantInstantiated))
// ... 
SomeClassIWantInstantiated instance = myFactory.Resolve<SomeClassIWantInstantiated>();

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

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