是否可以在autofac中注册开放的通用委托?

时间:2011-11-02 17:48:52

标签: function autofac

我想注册一个在运行时自行解析的通用委托,但我找不到在泛型上执行此操作的方法。

鉴于代表看起来像这样:

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 个答案:

答案 0 :(得分:4)

我只能提出注册源解决方案(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());

现在,我某些我无法将该代码输入网页并实际编译并运行,但它可能会接近:)