c# - 转换为具有动态类型参数的通用接口(interface)

标签 c# generics reflection type-inference

我有两个像这样的通用接口(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/

相关文章:

c# - 如何使用 2.4 C# Mongo 驱动程序运行解释查询?

c# - .NET 计时器异步运行吗?

c# - 如何使用泛型类为每个实例(或每个类型)设置 Xml 序列化属性

java - Android - 扩展泛型类

java - 限制 Java 中的类型以用于列表

c# - 工作单元和存储库模式

c++ - 如何将三个函数转换为一个泛型函数?

java - 使用反射使用用户定义的类数组参数调用方法

java - 我能从调试器信息中得到什么,而我不能通过反射得到?

c# - 使用 IsDefined 而不是 GetCustomAttributes 有好处吗