私は、同じオブジェクトグラフを複数のスレッドにまたがって深くクローンすることを含むプログラムの特定の部分のパフォーマンスを向上させようとしています。現在のところ、シンプルな実装であるシリアライゼーションを使用していますが、もっと速いものが必要です。私はILクローニングのアイデアを見つけ、here (Whizzo's Blog)というコードで作業しようとしています。C#Reflection IL - 値のコピー方法の理解
私は本当にまだとしてILを得ることはありませんので、私は誰かが少し手助けして(私はこれは、いくつかの最初の質問であると想像)私にはもののいくつかを説明することができます願っています。
opcodeとreflection.emitを説明する良いリンクがあれば誰でも良いでしょう。MSDNでは詳細はあまりありません)どのように値がコピーされていますか?私は、新しいオブジェクトを構築し、スタックその後少し後に関心のフィールド値を指定し、値が何らかの形でコピーされ
generator.Emit(OpCodes.Newobj, cInfo);
generator.Emit(OpCodes.Stloc, cloneVariable);
からポップされていることがわかります。私は元のオブジェクトに戻って元のオブジェクトが参照されていないように見えるときに、そのオブジェクトを取得する方法を理解していません。それともこれは(私はそれが何をするか、100%わからない)LocalBuilderのいくつかの魔法です:
// I *THINK* this Pushes the cloneVariable on the stack, loads an argument (from where?) and sets the field value based on the FieldInfo??
generator.Emit(OpCodes.Ldloc, cloneVariable);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, field);
generator.Emit(OpCodes.Stfld, field);
私はいつもディープクローンをしたいと私はそれがシリアル化されたフィールドに基づいて欲しいと、私は少しのコードを変更しました:あなたが持っている
private static T CloneObjectWithILDeep(T myObject)
{
Delegate myExec = null;
if (!_cachedILDeep.TryGetValue(typeof(T), out myExec))
{
// Create ILGenerator
DynamicMethod dymMethod = new DynamicMethod("DoDeepClone", typeof(T), new Type[] { typeof(T) }, Assembly.GetExecutingAssembly().ManifestModule, true);
ILGenerator generator = dymMethod.GetILGenerator();
LocalBuilder cloneVariable = generator.DeclareLocal(myObject.GetType());
ConstructorInfo cInfo = myObject.GetType().GetConstructor(Type.EmptyTypes);
generator.Emit(OpCodes.Newobj, cInfo);
generator.Emit(OpCodes.Stloc, cloneVariable);
foreach (FieldInfo field in typeof(T).GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public))
{
if(field.IsNotSerialized)
continue;
if (field.FieldType.IsValueType || field.FieldType == typeof(string))
{
generator.Emit(OpCodes.Ldloc, cloneVariable);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, field);
generator.Emit(OpCodes.Stfld, field);
}
else if (field.FieldType.IsClass)
{
CopyReferenceType(generator, cloneVariable, field);
}
}
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ret);
myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));
_cachedILDeep.Add(typeof(T), myExec);
}
return ((Func<T, T>)myExec)(myObject);
}
。 –
C#でしようとしていることを表現できますか? – thecoop
"同じオブジェクトグラフを繰り返し深くクローンする"本当にそれを行う必要がありますか?それをもっと速くしようとするのではなく、何とかそれを回避することはできませんか? – svick