我想在使用反射(查找接口实现)找到它之后,在使用泛型类的类上动态执行方法。
我陷入困境的一个例子如下。非常感谢帮助。
设置
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);
答案 0 :(得分:2)
您将不得不发出泛型方法的运行时类型特定版本。看看那个MethodInfo.MakeGenericMethod。
MakeGenericMethod方法允许您编写将特定类型分配给泛型方法定义的类型参数的代码,从而创建表示特定构造方法的MethodInfo对象。如果此MethodInfo对象的ContainsGenericParameters属性返回true,则可以使用它来调用方法或创建委托以调用该方法。
简而言之(伪)代码:
this.GetType()
.GetMethod("CheckForMessages")
.MakeGenericMethod(interfaceUsesType)
.Invoke(this, null);
答案 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});