Настройка фабрики делегатов Autofac, определенной в абстрактном классе - PullRequest
4 голосов
/ 23 сентября 2011

Я работаю над проектом на C #. Я пытаюсь избавиться от класса 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 не зарегистрировано. Этот шаблон фабрики делегатов не работает с абстрактными классами, и если да, есть ли другой способ сделать это?

1 Ответ

13 голосов
/ 23 сентября 2011

То, что вы ищете, это 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
        }
    }
}

Это использует подход внедрения зависимостей, если вы просто хотите разрешить фабрику:

var factory = Container.Resolve<IIndex<WidgetType,Widget>>();
...