是否有可能在autofac中注册一个开放的通用委托? [英] Is it possible to register an open generic delegate in autofac?

查看:311
本文介绍了是否有可能在autofac中注册一个开放的通用委托?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想注册一个可以在运行时自行解决的泛型委托,但是我找不到在泛型上做到这一点的方法。



给定一个看起来像这样的委托:

  public delegate TOutput Pipe   

给出一个离散注册的委托,如下所示:

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

我想注册一个函数这个行:

  builder.RegisterGeneric(typeof(Pipe<,>))。As(ctx => 
{
var typeArray = ctx.RequestedType.GetGenericArguments();
//这可以被记忆
var pipeDefinition = ctx.Resolve(typeof(AnonymousPipe<,>)。MakeGenericType (typeArray));

return pipeDefinition.GetPipe(ctx);

我无法找到在Autofac中提供通用实现作为参数的方法 - 我可能只是缺少一些东西,我知道我可以通过一个通用的对象或接口来实现,但我想坚持一个委托的轻松。它使得单元测试在注入这些元素时变得非常简单。

有什么想法?我现在必须做离散注册(每个类型组合一个,没有泛型)。

解决方案

我可以o只需拿出注册源解决方案(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(registerAccessor(anonPipeService)中的var anonPipeReg)
{
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()); 

现在,我确定我无法输入该代码进入一个网页并让它实际编译和运行,但它可能会接近:)


I want to register a generic delegate that resolves itself at runtime, but I cannot find a way to do this on generics.

Given a delegate that looks like this:

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

And given a discretely registered delegate that look like this:

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

I want to register a function along the lines of this:

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);

I cannot find a way to provide an implementation of the generic as a parameter in Autofac - I may just be missing something. I know I can do this through a generic object or interface, but I want to stick with the lightness of a delegate. It makes unit testing super simple on the injection of these.

Any thoughts? I am having to do discrete registrations at the moment(one per type combination and no generics).

解决方案

I can only come up with the registration source solution (the universal hammer in 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();
        }
    }
}

Then:

builder.RegisterSource(new PipeSource());

Now, I'm certain that I can't type that code into a web page and have it actually compile and run, but it might come close :)

这篇关于是否有可能在autofac中注册一个开放的通用委托?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆