动态且高性能地调用 DbSet 上的添加方法
我想对 DbSet 上的 Add 方法进行动态调用,但我在编译时不知道该方法。
实际上,通过简单的反射就可以实现,但性能很糟糕。这是我们现在使用的代码:
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
Object[] args = { entity };
method.Invokke(set, args);
我尝试了另外两种可能的错误,但出现了不同的错误。
第一个是使用委托
public delegate void MyDel<T>(T t,object entity);
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
Type template = typeof(MyDel<>);
Type specific = template.MakeGenericType(childClassType);
Delegate test = Delegate.CreateDelegate(specific, method);
,但在最后一行,我收到以下错误:绑定到目标方法
时出错第三个选项是使用像这样的表达式树:
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
ParameterExpression paramo = Expression.Parameter(typeSet, "param");
ParameterExpression parami = Expression.Parameter(typeSet, "newvalue");
Expression convertedParamo = Expression.Convert(paramo, typeof(Object));
Expression convertedParami = Expression.Convert(parami, typeof(Object));
MethodCallExpression methodCall = Expression.Call(convertedParamo, method, convertedParami);
Expression valueExp = Expression.Lambda(methodCall, paramo, parami);
Expression<Action<Object, Object>> dynamicExpression = (Expression<Action<Object, Object>>)valueExp;
Action<Object, Object> dynamicAction = dynamicExpression.Compile();
Object o = Activator.CreateInstance(otherType);
dynamicAction(o, entity);
但在这种情况下,在“Expression.Call(convertedParamo)”行,方法,..
我收到此错误:
方法'DictionnaireONYX.Entites.ArticleSansFacturier Add(DictionnaireONYX.Entites.ArticleSansFacturier)' 在类型上声明 'System.Data.Entity.DbSet`1[DictionnaireONYX.Entites.ArticleSansFacturier]' 无法使用“System.Object”类型的实例进行调用
,其中 ArticleSansFacturier 是 DbSet。
谁能帮助我?
提前致谢
i would like to make a dynamic call on the Add method on DbSet that i don't know at the compilation.
Actually, it's possible with simple reflection but the performance are awful. Here is the code we are using now :
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
Object[] args = { entity };
method.Invokke(set, args);
i've tried two others possibilities with different errors.
The first other is to use delegate
public delegate void MyDel<T>(T t,object entity);
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
Type template = typeof(MyDel<>);
Type specific = template.MakeGenericType(childClassType);
Delegate test = Delegate.CreateDelegate(specific, method);
but on the last line, i get the following error : Error binding to target method
And the third option is to use expression tree like this :
Type contextType = (context as Object).GetType();
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null);
Type typeSet = set.GetType();
MethodInfo method = typeSet.GetMethod("Add");
ParameterExpression paramo = Expression.Parameter(typeSet, "param");
ParameterExpression parami = Expression.Parameter(typeSet, "newvalue");
Expression convertedParamo = Expression.Convert(paramo, typeof(Object));
Expression convertedParami = Expression.Convert(parami, typeof(Object));
MethodCallExpression methodCall = Expression.Call(convertedParamo, method, convertedParami);
Expression valueExp = Expression.Lambda(methodCall, paramo, parami);
Expression<Action<Object, Object>> dynamicExpression = (Expression<Action<Object, Object>>)valueExp;
Action<Object, Object> dynamicAction = dynamicExpression.Compile();
Object o = Activator.CreateInstance(otherType);
dynamicAction(o, entity);
But in this case, at the line "Expression.Call(convertedParamo, method,..
i got this error :
Method 'DictionnaireONYX.Entites.ArticleSansFacturier
Add(DictionnaireONYX.Entites.ArticleSansFacturier)' declared on type
'System.Data.Entity.DbSet`1[DictionnaireONYX.Entites.ArticleSansFacturier]'
cannot be called with instance of type 'System.Object'
where ArticleSansFacturier is the DbSet.
Who can help me ?
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不得不说,我现在不知道性能如何,但对代码进行一些更改后,它似乎可以工作。尤其是最后的动态部分可能会出现一些问题。
我使用了 ModelContext 并在其中设置了作者。
I have to say I don't now how the performance is but after making a few changes to your code it seems to work. Especially the dynamic part at the end could give some problems.
I'v used a ModelContext with a Authors set in it.
如果您使用 .NET 4.0,您可以使用“dynamic”关键字 - 这是最好、最高效的方法。
它看起来像这样:
我不确定我是否 100% 理解你的代码,所以不确定这正是你想要做的,但这是一般的想法。
进一步阅读:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
If you are using .NET 4.0 you can use the "dynamic" keyword - that's the best and most performant way.
It will look something like this:
I'm not sure I understand your code 100%, so not sure that's exactly what you are trying to do, but that's the general idea.
Further reading:
http://msdn.microsoft.com/en-us/library/dd264736.aspx