Настройка фабрики делегатов Autofac, определенной в абстрактном классе

Я работаю над проектом С#. Я пытаюсь избавиться от класса Factory с большим оператором switch.

Я хочу настроить Autofac так, чтобы он мог создавать зависимость на основе параметра, тем самым позволяя Autofac занять место Factory.

Я просмотрел страницу DelegateFactories вики Autofac, но не могу Не могу понять, как применить шаблон к абстрактному классу. Вот код, показывающий ситуацию:

public enum WidgetType
{
    Sprocket,
    Whizbang
}

public class SprocketWidget : Widget
{
}

public class WhizbangWidget : Widget
{
}

public abstract class Widget
{
    public delegate Widget Factory(WidgetType widgetType);
}

public class WidgetWrangler
{
    public Widget Widget { get; private set; }

    public WidgetWrangler(IComponentContext context, WidgetType widgetType)
    {
        var widgetFactory = context.Resolve<Widget.Factory>();
        Widget = widgetFactory(widgetType);
    }
}

Я хотел бы, чтобы, если бы я сказал new WidgetWrangler(context, WidgetType.Sprocket), его свойство Widget было бы SpocketWidget.

Когда я пытаюсь это сделать, я получаю сообщения о том, что Widget.Factory не зарегистрирован. Этот шаблон фабрики делегатов не работает с абстрактными классами, и если да, то есть ли другой способ сделать это?


person neontapir    schedule 22.09.2011    source источник


Ответы (1)


Вам нужен тип отношений IIndex<,>.

Если вы регистрируете свои подклассы с помощью .Keyed<>(...), вы можете указать для регистрации значение (object).

Например:

builder.RegisterType<SprocketWidget>()
   .Keyed<Widget>(WidgetType.Sproket)
   .InstancePerDependency();

builder.RegisterType<WhizbangWidget>()
   .Keyed<Widget>(WidgetType.Whizbang)
   .InstancePerDependency();

Тогда вам потребуется только зависимость IIndex<WidgetType,Widget> для имитации заводского поведения.

public class SomethingThatUsesWidgets
{    
    private readonly IIndex<WidgetType,Widget> _widgetFactory;
    public SomethingThatUsesWidgets(IIndex<WidgetType,Widget> widgetFactory)
    {
        if (widgetFactory == null) throw ArgumentNullException("widgetFactory");
        _widgetFactory = widgetFactory;
    }

    public void DoSomething()
    {
        // Simple usage:
        Widget widget = widgetFactory[WidgetType.Whizbang];

        // Safe Usage:
        Widget widget2 = null;
        if(widgetFactory.TryGetValue(WidgetType.Sprocket, out widget2))
        {
            // do stuff
        }
    }
}

Это использует подход Dependency Injection, если вы просто хотите разрешить фабрику:

var factory = Container.Resolve<IIndex<WidgetType,Widget>>();
person Aren    schedule 23.09.2011
comment
+1 IIndex определенно подход, учитывая, что в ОП указано перечисление. Однако я бы обновил ваш пример, чтобы сохранить фабрику в переменной-члене и использовать ее в вызове метода. Это отделяет фазу инициализации от фазы выполнения, что существенно снижает проблемы со временем. См. пример модема здесь: code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices< /а> - person Bryan Watts; 23.09.2011
comment
Я обновил пример до чего-то более похожего на то, как это можно использовать. Первоначальный пример был просто быстрым просмотром кода реализации. - person Aren; 24.09.2011