我想注册一个可以在运行时自行解决的泛型委托,但是我找不到在泛型上做到这一点的方法。
给定一个看起来像这样的委托:
public delegate TOutput Pipe我想注册一个函数这个行:
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中注册一个开放的通用委托?
发布评论