使用另一个通用方法的结果的参数调用通用接口的方法 [英] Invoke a method from a generic interface with a parameter of a result of another generic method
问题描述
我试图创建一个类来绑定继承特定接口的所有类,以便在由自定义实体框架模型构建器触发的事件中执行。我有什么:
$ b $ 1)通用接口IOverride,它有一个方法Configure(EntityTypeConfiguration实体)
2 )几个实现接口的类。
public class ItemOverride:IOverride< Item>
{
public void Configure(EntityTypeConfiguration< Item> entity)
{
//用实体
做些事情}
}
code>
3)一种方法,收集定义接口的所有类,并将它们组合成一个IOverride列表,如下所示:
var list =(from assembly.GetTypes()中的x $ b $ x from x.GetInterfaces()
let y = x.BaseType
where
(y!= null&& y.IsGenericType&&
typeof(IOverride<>)。IsAssignableFrom(y.GetGenericTypeDefinition())) ||
(z.IsGenericType&&
typeof(IOverride<>)。IsAssignableFrom(z.GetGenericTypeDefinition()))
select z).ToList();
4)我尝试通过在事件中调用配置方法来追踪它... (配置)
var entityMethod = typeof(DbModelBuilder) .GetMethod( 实体);
foreach(var中的项目)
{
var target = item.GetGenericArguments()。Single();
var invoked = entityMethod.MakeGenericMethod(target).Invoke(args.ModelBuilder,new object [] {});
var func = method.MakeGenericMethod(item);
ModelCreating + =(o,eventArgs)=> func.Invoke(被调用,新对象[] {});
}
然而,当运行实际事件时,我得到
附加信息:无法在ContainsGenericParameters为true的类型或方法上执行后期操作。
func.Invoke()行中的异常。我显然做错了什么,但我不是100%确定它是什么。我想,当我感觉天气不好或者我做了一件非常愚蠢的事情时,思考可能让我感到困惑。无论如何,在正确的方向微调就可以了。
问题在于您从 IOverride<>
,而不是真正的类型。所以它没有引用继承者。而且当你调用 func.Invoke
时,你应该传递 IOverride<>
的继承者实例,现在你是传入 EntityTypeConfiguration< T>
,您可以在调用的
变量中获得。但是这个变量应该作为参数。
这是一个工作示例。
var entityMethod = typeof(DbModelBuilder).GetMethod(Entity);
var builder = args.ModelBuilder;
foreach(在assembly.GetTypes()中输入x)
{
foreach(在x.GetInterfaces()中输入z)
{
类型y = x.BaseType ; (y!= null&& y.IsGenericType&& typeof(IOverride<>)。IsAssignableFrom(y.GetGenericTypeDefinition()))||
(z.IsGenericType& amp; ;& typeof(IOverride<>)IsAssignableFrom(z.GetGenericTypeDefinition())))
{
//第一个区别 - 我们从实际对象获得Configure方法,而不是从IOverride
var method = x.GetMethod(Configure);
var target = z.GetGenericArguments()。Single();
var invoked = entityMethod.MakeGenericMethod(target).Invoke(builder,new object [] {});
var func = method.MakeGenericMethod(typeof(string));
//这一块可以进入ModelCreating事件,如您的示例中的
//但是在本地我没有使用它
//第二个区别 - 我们创建原始类型的实例
var obj = Activator.CreateInstance(x);
//第三个区别 - 我们将实例作为`this`传递,并将参数传递为参数
func.Invoke(obj,new [] {invoked});
code $ pre
I'm trying to make a class which binds all classes which inherit a certain interface to be executed in an event fired by a custom entity framework model builder.
What I have:
1) A generic interface IOverride which has a method Configure(EntityTypeConfiguration entity)
2) Several classes that implement the interface.
public class ItemOverride : IOverride<Item>
{
public void Configure(EntityTypeConfiguration<Item> entity)
{
// Do something with entity
}
}
3) A method which gathers all classes which define the interface and combines them into a list of IOverride's like this:
var list = (from x in assembly.GetTypes()
from z in x.GetInterfaces()
let y = x.BaseType
where
(y != null && y.IsGenericType &&
typeof (IOverride<>).IsAssignableFrom(y.GetGenericTypeDefinition())) ||
(z.IsGenericType &&
typeof (IOverride<>).IsAssignableFrom(z.GetGenericTypeDefinition()))
select z).ToList();
4) I try to follow that up with invoking the method Configure in an event...
var method = typeof (IOverride<>).GetMethod("Configure")
var entityMethod = typeof (DbModelBuilder).GetMethod("Entity");
foreach (var item in list)
{
var target = item.GetGenericArguments().Single();
var invoked = entityMethod.MakeGenericMethod(target).Invoke(args.ModelBuilder, new object[] {});
var func = method.MakeGenericMethod(item);
ModelCreating += (o, eventArgs) => func.Invoke(invoked, new object[] {});
}
However, when running the actual event, I'm getting a
Additional information: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
Exception on the func.Invoke() line. I'm clearly doing something wrong, but I'm not 100% sure what it is. I'm thinking maybe Reflection is confusing me when I'm feeling under the weather or maybe I just did something incredibly stupid. Anyway a nudge in the right direction could suffice.
解决方案 The problem is that you are getting method from IOverride<>
and not from real type. So it hasn't references to inheritor. And also when you call func.Invoke
you should pass instance of inheritor of IOverride<>
, and now you are passing EntityTypeConfiguration<T>
that you get in invoked
variable. But this variable should go as parameter.
Here is working example.
var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
var builder = args.ModelBuilder;
foreach (Type x in assembly.GetTypes())
{
foreach (Type z in x.GetInterfaces())
{
Type y = x.BaseType;
if ((y != null && y.IsGenericType && typeof(IOverride<>).IsAssignableFrom(y.GetGenericTypeDefinition())) ||
(z.IsGenericType && typeof(IOverride<>).IsAssignableFrom(z.GetGenericTypeDefinition())))
{
// first difference - we get Configure method from real object, and not from IOverride
var method = x.GetMethod("Configure");
var target = z.GetGenericArguments().Single();
var invoked = entityMethod.MakeGenericMethod(target).Invoke(builder, new object[] { });
var func = method.MakeGenericMethod(typeof(string));
// this one block can go to ModelCreating event as in your example,
// but locally i didn't use it
// second difference - we create instance of original type
var obj = Activator.CreateInstance(x);
// third one difference - we pass instance as `this` and pass invoked as parameter
func.Invoke(obj, new[] { invoked });
}
}
}
这篇关于使用另一个通用方法的结果的参数调用通用接口的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!