我有两个像这样的通用接口(interface):
public interface IFoo<T> { }
public interface IBar<TFoo, T> where TFoo : Foo<T> {
T Qux(TFoo foo);
}
IFoo<T>
有一堆实现,每个都有一个匹配的实现 IBar<S,T>
,在我的 IoC 容器中注册(恰好是 CaSTLe.Windsor)。
现在,我想创建一个方法,该方法基于实现 IFoo<T>
的某种类型的参数, 返回对应的 IBar<IFoo<T>,T>
来自温莎。一个天真的实现看起来像这样:
public IBar<TFoo,T> GetBarFor(IFoo<T> foo) where TFoo : IFoo<T>
{
return container.Resolve<IBar<TFoo,T>>();
}
但是,在调用代码中,我没有具体类型的 Foo<T>
- 只是一个 IFoo<T>
:
public T DoStuffWithStuff<T>(IFoo<T> foo)
{
var bar = GetBarFor(foo);
return bar.Qux(foo);
}
并且在这个调用中,编译器无法推断出类型参数(具体来说,我猜是 TFoo
),所以我需要采取另一种方法。
我尝试用 Resolve()
的非通用版本解析类型, 但后来我无法获得正确的返回类型:
public AbstractBar<T> GetBarFor(IFoo<T> foo) where TFoo : IFoo<T>
{
var barType = typeof(IBar<,>).MakeGenericType(foo.GetType(),typeof(T));
var bar = container.Resolve(barType); // bar is now a System.Object
var wrapperType = typeof(BarWrapper<,>).MakeGenericType(foo.GetType(), typeof(T));
var wrapper = Activator.CreateInstance(wrapperType, bar);
return (AbstractBar<T>)wrapper;
}
与
public abstract class AbstractBar<T> { public abstract T Qux(IFoo<T> foo); }
public class BarWrapper<TFoo, T> : AbstractBar<T> where TFoo : IFoo<T>
{
private IBar<TFoo,T> _inner;
public BarWrapper(IBar<TFoo,T> inner) { _inner = inner; }
public T Qux(IFoo<T> foo) { return _inner.Qux((TFoo)foo); }
}
但我不断收到关于 Activator.CreateInstance
的异常打电话说 BarWrapper
的构造函数找不到(是的,一切都是 public
)。
在DoStuffWithStuff
有没有什么好的方法可以接电话?上面正是为那个签名工作(即我不能从调用代码中推迟任何更具体的泛型)?
脚注:我在 Jimmie Bogard's MediatR implementation of the mediator pattern 中看到后一种模式有效,事实上,我在这里试图完成的是一个非常相似的实现,它不依赖于公共(public)服务定位器,而是直接进入我们的 IoC 容器。在上下文中,IFoo<T>
真的是IRequest<out TResponse>
, IBar<TFoo, T>
真的是IRequestHandler<in TRequest, out TResponse>
等
查看他的代码并尝试重新创建它但调用 Windsor 容器而不是服务定位器,我无法弄清楚为什么他的代码有效,而我的代码却无效。
最佳答案
未经测试,但您需要使用反射将类型后期绑定(bind)到您要执行的泛型的方法信息。
var wrapperType = typeof(BarWrapper<,>).MakeGenericType(foo.GetType(), typeof(T));
MethodInfo TempMethodInfo = typeof(MYClass).GetMethod("DoStuffWithStuff")
MethodInfo GenericParam = TempMethodinfo.MakeGenericMethod(T);
var Formatter = Delegate.CreateDelegate(wrapperType , GenericParam);
关于c# - 转换为具有动态类型参数的通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26550497/