Можно ли зарегистрировать открытый общий делегат в autofac? - PullRequest
5 голосов
/ 02 ноября 2011

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

С учетом делегата, который выглядит следующим образом:

public delegate TOutput Pipe<in TInput, out TOutput>(TInput input);

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

public class AnonymousPipe<TInput, TOutput>
{
   public Pipe<TInput, TOutput> GetPipe(IContext context)
   {...}

Я хочу зарегистрировать функцию в соответствии с этим:

builder.RegisterGeneric(typeof(Pipe<,>)).As(ctx => 
{
   var typeArray = ctx.RequestedType.GetGenericArguments();
   // this can be memoized 
   var pipeDefinition = ctx.Resolve(typeof(AnonymousPipe<,>).MakeGenericType(typeArray));

   return pipeDefinition.GetPipe(ctx);

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

Есть мысли?Мне нужно сделать отдельные регистрации в данный момент (по одной на комбинацию типов и без генериков).

1 Ответ

5 голосов
/ 03 ноября 2011

Я могу только предложить исходное решение для регистрации (универсальный молоток в Autofac.)

class PipeSource : IRegistrationSource
{
    public bool IsAdapterForIndividualComponents { get { return true; } }

    public IEnumerable<IComponentRegistration> RegistrationsFor(
        Service service,
        Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        var swt = service as IServiceWithType;
        if (swt == null || !swt.ServiceType.IsGenericType)
            yield break;

        var def = swt.ServiceType.GetGenericTypeDefinition();
        if (def != typeof(Pipe<,>))
            yield break;

        var anonPipeService = swt.ChangeType(
            typeof(AnonymousPipe<,>).MakeGenericType(
                swt.ServiceType.GetGenericArguments()));

        var getPipeMethod = anonPipeService.ServiceType.GetMethod("GetPipe");

        foreach (var anonPipeReg in registrationAccessor(anonPipeService))
        {
            yield return RegistrationBuilder.ForDelegate((c, p) => {
                    var anon = c.ResolveComponent(anonPipeReg, p);
                    return getPipeMethod.Invoke(anon, null); })
                .As(service)
                .Targeting(anonPipeReg)
                .CreateRegistration();
        }
    }
}

Тогда:

builder.RegisterSource(new PipeSource());

Теперь я уверен , что я не могу набрать этот код на веб-странице и заставить его фактически скомпилироваться и запустить, но он может приблизиться:)

...