Autofac: регистрация Func <> или Factory? - PullRequest
7 голосов
/ 03 марта 2012

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

Подход 1: регистрация выделенных фабрик

...
builder.RegisterType<MTextField>().Keyed<IComponent>(typeof(TextFieldProperties));
builder.RegisterType<ComponentFactory>().As<IComponentFactory>();

public class ComponentFactory : IComponentFactory
{
    private readonly IIndex<Type, IComponent> _lookup;

    public ComponentFactory(IIndex<Type, IComponent> lookup)
    {
        _lookup = lookup;
    }

    public IComponent Create(ComponentProperties properties)
    {
        var component = _lookup[properties.GetType()];
        component.Transform(properties);
        return component;
    }
}

Подход 2: регистрация в соответствии с функциями

...
builder.RegisterType<MTextField>().Keyed<IComponent>(typeof(TextFieldProperties));
builder.Register<Func<ComponentProperties, IComponent>>(c =>
{
    var context = c.Resolve<IComponentContext>();
    return properties =>
    {
        var component = context.ResolveKeyed<IComponent>(properties.GetType());
        component.Transform(properties);
        return component;
    };
});

Вопросы:

Я думаю, это может быть субъективно, но я все равно хотел спросить.

  • Какой подход предпочтительнее и почему?
  • Есть ли даже лучшее решение?
  • Действительно ли необходимо хранить контекст в «подходе 2»?

EDIT

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

public class TransformerFactory<D, T> : ITransformFactory<D, T>
    where T : ITransform<D>
{
    private readonly IIndex<Type, T> _lookup;


    public TransformerFactory(IIndex<Type, T> lookup)
    {
        _lookup = lookup;
    }


    public T Create(D data, Action<T> prepareInstance = null)
    {
        var instance = _lookup[data.GetType()];
        if (prepareInstance != null)
        {
            prepareInstance(instance);
        }
        instance.Transform(data);
        return instance;
    }
}

builder.RegisterGeneric(typeof(TransformerFactory<,>)).As(typeof(ITransformFactory<,>)); 
// e.g. var x = container.Resolve<ITransformFactory<ComponentProperties, IComponent>>();

1 Ответ

0 голосов
/ 29 апреля 2018

Первый подход представляется предпочтительным. Я предлагаю две причины:

  1. Keyed и IIndex обеспечивают достаточное и чистое готовое решение для поставленной задачи. Принимая во внимание, что подход 2 использует более обобщенный инструмент, который требует дополнительной логики для вашей работы (т.е. вы пишете код для вызова ResolveKeyed). Если есть простое решение для конкретной цели, используйте его вместо более общего решения.

  2. Подход 1 сможет правильно управлять временем жизни и областями действия. Подход 2, как вы подняли, захватывает контекст и разрешит отдельные экземпляры в этом контексте. Это означает, что время жизни отдельных экземпляров будет зависеть от объема и срока службы фабрики, а не от политики времени жизни, указанной для отдельных служб.

...