2011-10-24 7 views
0

コンパイル時にわからないDbSetのAddメソッドで動的呼び出しを行いたいと思います。DbSetで動的にperformantメソッドを呼び出す

実際には、単純な反射でも可能ですが、パフォーマンスはひどいです。ここで使用しているコードは次のとおりです。

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); 

私はさまざまなエラーで2つの可能性を試しました。

最初の他、デリゲート

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 追加(DictionnaireONYX.Entites.ArticleSansFacturier)' はSystem.Data.Entity.DbSet`1 [DictionnaireONYX.Entites.ArticleSansFacturier」タイプ で宣言] ' ' System.Object 'タイプのインスタンスで呼び出すことはできません

ここで、ArticleSansFacturierはDbSetです。

誰が私を助けることができますか?事前

+0

これは、関連するさまざまな種類が何であるかは明らかではありません。 'typeSet'は実際にセットの型か要素の型ですか?あなたは両方の異なる点でそれを使用しているようです。どのようにこれを使用しようとしているのかの具体的な例を与えることができれば、そのタイプを見ることができます。 –

+0

これは役に立ちますか?:https://github.com/maxbeaudoin/MagicDbModelBuilder – maxbeaudoin

答えて

0

おかげで私は今のパフォーマンスがどのようにしないと言っているが、あなたのコードにいくつかの変更を行った後、動作しているようです。特に最後のダイナミックな部分はいくつか問題を引き起こす可能性があります。

ModelContextをAuthorsがセットされた状態で使用しました。

ModelContext context = new ModelContext(); 

Author entity = new Author(); 

string entitySetName = "Authors"; 
string methodName = "AddObject"; 

Type contextType = (context as Object).GetType(); 
var set = (contextType.GetProperty(entitySetName)).GetValue(context, null); 
Type typeSet = set.GetType(); 
MethodInfo method = typeSet.GetMethod(methodName); 

ParameterExpression paramo = Expression.Parameter(typeSet, "param"); 
ParameterExpression parami = Expression.Parameter(entity.GetType(), "newvalue"); 

MethodCallExpression methodCall = Expression.Call(paramo, method, parami); 

Type typeofClassWithGenericStaticMethod = typeof(Expression); 
MethodInfo methodInfo = typeofClassWithGenericStaticMethod.GetMethods().Where(m => m.Name == "Lambda" && m.IsGenericMethod).First(); 
Type genericArguments = typeof(Action<,>).MakeGenericType(typeSet, entity.GetType()); 
MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments); 

dynamic objectSet = set; 
dynamic returnValue = genericMethodInfo.Invoke(null, new object[] { methodCall, new ParameterExpression[] { paramo, parami } }); 
var action = returnValue.Compile(); 

action(objectSet, entity); 
+0

返信いただきありがとうございます。私はあなたのコードを試みたが、私はアクション(objectSet、エンティティ) - > Microsoft.Csharp.RunTimeBinderを行う例外が表示されます。RunTimeBinderException:デリゲートがいくつかの無効な引数を使用する – user1005016

+0

何がうまくいかないのか分かりません。コードをローカルでテストしたところ、動作しています。このコードをObjectContextまたはDbContextに対して実行していますか? –

+0

ここはDbContextです – user1005016

0

.NET 4.0を使用している場合は、「ダイナミック」キーワードを使用できます。これは、最も効果的な方法です。 それは次のようなものになります。

Type contextType = (context as Object).GetType(); 
dynamic set = (contextType.GetProperty(entitySetName)).GetValue(context, null); 
set.Add(args); 

を私はあなたのコードを100%理解していない、そうではないことは、あなたがやろうとしているまさにだと確信し、それは一般的な考えです。

さらに読書: http://msdn.microsoft.com/en-us/library/dd264736.aspx

+0

を返信してくれてありがとう。set.Add(...) - > System.Reflection.TargetInvocationExceptionを実行して例外が発生する。 – user1005016

+0

これは、「追加」機能内に例外がスローされたことを意味します。 この例外のInnerExceptionプロパティを確認し、問題点を確認してください。 さらに助けが必要な場合は、内部例外タイプ、メッセージ、スタックトレースを投稿してください。 – Svarog

関連する問題