Свободная конфигурация нескольких регистраций - PullRequest
1 голос
/ 22 декабря 2011

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

public static IRegistrationBuilder<?, ?, ?> 
  RegisterChannel<T>(this ContainerBuilder builder, Func<IComponentContext, ChannelFactory<T>> @delegate)
{
  // channelfactory and sharedchannel should have same lifetime configuration
  var channelfactoryreg = builder.Register(c => @delegate(c));
  var sharereg = builder.RegisterType<Wcf.SharedChannel<T>>();

  // is it possible to combine them and return?
  return ???;
}

Как мне заполнить пробелы, чтобы я мог написать (например) builder.RegisterTwo().SingleInstance()? Можно ли прямо или косвенно «объединить» два IRegistrationBuilderTLAR объекта, чтобы при настройке результата настраивались все базовые регистрации, или есть другой способ сделать это?

В более общем смысле: есть ли учебник для работы с внутренними компонентами Autofac?

Спасибо за ваше время.

Ответы [ 3 ]

0 голосов
/ 23 декабря 2011

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

public class MyRegistrationSource : IRegistrationSource
{
    /// <summary>
    /// Gets a value indicating whether the registrations provided by this source are 1:1 adapters on top
    /// of other components (I.e. like Meta, Func or Owned.)
    /// </summary>
    public bool IsAdapterForIndividualComponents
    {
        get
        {
            return false;
        }
    }

    /// <summary>
    /// Retrieve registrations for an unregistered service, to be used
    /// by the container.
    /// </summary>
    /// <param name="service">The service that was requested.</param>
    /// <param name="registrationAccessor">A function that will return existing registrations for a service.</param>
    /// <returns>
    /// Registrations providing the service.
    /// </returns>
    public IEnumerable<IComponentRegistration> RegistrationsFor(
        Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        var swt = service as IServiceWithType;
        if (swt != null)
        {
            // Register requested service types that pass some test or other
            if (swt.ServiceType.HasAttribute<SomeAttribute>(true) ||
                typeof(SomeType).IsAssignableFrom(swt.ServiceType))
            {
                var registration = RegistrationBuilder.ForType(swt.ServiceType)
                    .InstancePerDependency()
                    .CreateRegistration();
                yield return registration;
            }
        }
    }
}
0 голосов
/ 19 апреля 2012

Черт возьми, я ненавижу отвечать на свой вопрос, но все предложенные альтернативы казались не по теме или слишком сложными.Комментарий Ника оказался наиболее близким к интересному, но только полностью отпугнул меня от внутренних органов Autofac;).Я исследовал, но это было излишним для моей ситуации.

Я закончил тем, что разделил разницу (как подразумевается в моем комментарии выше), отказался от свободного интерфейса, но все же допускал гибкое продолжение регистрации, принимая конфигурациюв самом методе:

    public static void RegisterSharedChannel<T>(this ContainerBuilder builder, Func<IComponentContext, ChannelFactory<T>> @delegate, 
        Action<Autofac.Builder.IRegistrationBuilder<object, Autofac.Builder.IConcreteActivatorData, Autofac.Builder.SingleRegistrationStyle>> config)
    {
        builder.Register(c => c.Resolve<Wcf.ISharedChannel<T>>().GetChannel()).ExternallyOwned();
        //would be really nice to be able to retain the fluency of the interface, but: /4451375/svobodnaya-konfiguratsiya-neskolkih-registratsii
        //this should suffice for now...
        var facreg = builder.Register(c => @delegate(c));
        var sharereg = builder.RegisterType<Wcf.SharedChannel<T>>().AsImplementedInterfaces();
        config(facreg);
        config(sharereg);
    }

Синтаксис вызова не так хорош (например:

builder.RegisterSharedChannel(c => BuildChannelFactory(...), r => r.SingleInstance());

, но все (большая часть?) гибкости все еще там.

0 голосов
/ 22 декабря 2011

Вы должны использовать модуль для инкапсуляции регистраций, которые имеют смысл вместе.

ИМХО, вам следует звонить .SingleInstance() в обе регистрации. Если это две службы, они должны быть настроены дважды. Если они имеют больше общих черт в регистрации, вы можете зарегистрировать их с помощью Assembly Scanning .

...