用通用类型执行类的反射

时间:2018-06-11 10:38:29

标签: c# .net-core

我想在使用反射(查找接口实现)找到它之后,在使用泛型类的类上动态执行方法。

我陷入困境的一个例子如下。非常感谢帮助。

设置

public interface IActionRequired<T> where T : class {
    void DoThis(T[] receivedObjects);
}

public class BookDetails {
    public int BookId { get; set; }

    public string BookName { get; set; }
}

public class LibraryBookReturned : IActionRequired<BookDetails>
{
    public void DoThis(BookDetails[] receivedObjects)
    {
        foreach(var book in receivedObjects)
            System.Console.WriteLine(book.BookName);
    }
}

使用反射的示例尝试

下面,我只是使用第一个实现,但在现实世界中,我将使用命名约定来找到正确的实现。

        var assembly = Assembly.GetCallingAssembly();
        var listOfImplementations = 
                GetAllTypesImplementingOpenGenericType(typeof(IActionRequired<>), assembly);
        var implementation = listOfImplementations.FirstOrDefault();
        var implementationUsesInterface = implementation.GetInterfaces() [0];
        var interfaceUsesType = implementationUsesInterface.GetGenericArguments() [0];

我知道下面的内容不起作用(我得到一个错误,说interfaceUsesType是一个变量而不是一个类型),但它表明了我想做的事情:

        var instance = 
            assembly.CreateInstance(implementation.FullName) as IActionRequired<interfaceUsesType>;
        var results = this.CheckForMessages<interfaceUsesType>();
        instance.DoThis(results);

2 个答案:

答案 0 :(得分:2)

您将不得不发出泛型方法的运行时类型特定版本。看看那个MethodInfo.MakeGenericMethod

  

MakeGenericMethod方法允许您编写将特定类型分配给泛型方法定义的类型参数的代码,从而创建表示特定构造方法的MethodInfo对象。如果此MethodInfo对象的ContainsGenericParameters属性返回true,则可以使用它来调用方法或创建委托以调用该方法。

简而言之(伪)代码:

this.GetType()
    .GetMethod("CheckForMessages")
    .MakeGenericMethod(interfaceUsesType)
    .Invoke(this, null);

您也可以在此处阅读:How To: Call a generic method with a runtime type

答案 1 :(得分:0)

@rickvbosch的答案是(非常接近)我需要的东西,绝对是正确的方法。然而,由于我试图有效地做两件事,我已经提出了他的答案,并添加了我所做的工作,以使用他的建议作为我原来问题的公认答案。

        var instance = Activator.CreateInstance(implementation);
        var results = this.GetType()
            .GetMethod("CheckForMessages", BindingFlags.NonPublic | BindingFlags.Instance)
            .MakeGenericMethod(interfaceUsesType)
            .Invoke(this, null) as object[];

        if(results.Count() > 0)
            instance.GetType()
            .GetMethod("DoThis")
            .Invoke(instance, new object[] {results});