我想注册一个在运行时自行解决的通用委托,但是我找不到在通用代理上执行此操作的方法。
给定一个看起来像这样的代表:
public delegate TOutput Pipe<in TInput, out TOutput>(TInput input);
Run Code Online (Sandbox Code Playgroud)
并给一个离散注册的委托,看起来像这样:
public class AnonymousPipe<TInput, TOutput>
{
public Pipe<TInput, TOutput> GetPipe(IContext context)
{...}
Run Code Online (Sandbox Code Playgroud)
我想按照以下方式注册一个函数:
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);
Run Code Online (Sandbox Code Playgroud)
我找不到在Autofac中作为参数提供泛型实现的方法-我可能只是缺少了一些东西。我知道我可以通过通用对象或接口来做到这一点,但我想坚持委托的轻巧性。这使得注入这些单元测试超级简单。
有什么想法吗?我现在必须进行离散注册(每个类型组合一个,没有泛型)。
我只能提出注册源解决方案(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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
builder.RegisterSource(new PipeSource());
Run Code Online (Sandbox Code Playgroud)
现在,我确定我无法将该代码键入到网页中并让其实际编译和运行,但可能会很接近:)