StructureMap и фабричные классы - PullRequest
2 голосов
/ 11 июня 2011

В моем коде есть сом-фабричные классы, и мне не нравится вызов Structermap. Как мне сделать это правильно?

class ManagerBaseFactory
{
    public ManagerBase GetInstance(SomeEnum e)
    {
        Type t;

        switch (e)
        {
            case SomeEnum.A:
                t = typeof(Manager1);
            case SomeEnum.B:
                t = typeof(Manager2);
            case SomeEnum.C:
                t = typeof(Manager3);
        }
        return (ManagerBase)StructureMap.ObjectFactory.GetInstance(t);
    }
}

Ответы [ 3 ]

2 голосов
/ 24 июня 2011

Если вы абсолютно не хотите, чтобы ваш ManagerBaseFactory использовал контейнер, вы можете предоставить ему доступ ко всем реализациям ManagerBase из контейнера и заставить его вернуть правильное значение.Когда StructureMap видит IEnumerable типа в конструкторе, он внедряет все экземпляры этого типа, о которых он знает.

class ManagerBaseFactory
{
    private readonly IEnumerable<ManagerBase> _managers;

    public ManagerBaseFactory(IEnumerable<ManagerBase> managers)
    {
        _managers = managers;
    }

    public ManagerBase GetInstance(SomeEnum e)
    {
        Type t;

        switch (e)
        {
            case SomeEnum.A:
                t = typeof(Manager1);
                break;
            case SomeEnum.B:
                t = typeof(Manager2);
                break;
            case SomeEnum.C:
                t = typeof(Manager3);
                break;
            default:
                return null;
        }
        return _managers.FirstOrDefault(m => m.GetType().Equals(t));
    }
}

И, конечно, вы должны убедиться, что все ваши реализации ManagerBase загружены вконтейнер:

var container = new Container(x =>
{
    x.Scan(scan =>
    {
        scan.TheCallingAssembly();
        scan.AddAllTypesOf<ManagerBase>();
    });
});
2 голосов
/ 11 июня 2011

Я не вижу проблемы в использовании структуры карты таким образом.Что вам не нравится в текущем решении?

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

public class ServicesRegistry : Registry
{
    public ServicesRegistry()
    {
        For< ManagerBase >().Use< Manager1 >().Named("A");
        For< ManagerBase >().Use< Manager2 >().Named("B");
        For< ManagerBase >().Use< Manager3 >().Named("C");
    }
}

Вы можете получить правильную ссылку, просто позвонив

SomeEnum e = SomeEnum.A;
ObjectFactory.GetNamedInstance<ManagerBase>(e.ToString());
0 голосов
/ 11 июня 2011

Не ясно, на какую часть вы возражаете.Одно из улучшений, которое вы могли бы сделать, - иметь в своем конструкторе ManagerBaseFactory взятие IContainer, которое вы можете использовать вместо статического шлюза ObjectFactory.Затем вы можете вытащить ManagerBaseFactory из контейнера, и контейнер впрыснет себя на завод.Фабрику будет проще проводить модульное тестирование без статической зависимости.

Вы также можете поместить операторы возврата непосредственно в коммутатор, чтобы вы могли воспользоваться обобщениями:

case SomeEnum.A:
  return _container.GetInstance<Manager1>();
...