C # Reflection IL - understanding how values ​​are copied

I am trying to improve the performance of a certain part of my program, which includes deep cloning of the same object graph multiple times. I am currently using serialization, which is an easy easy implementation, but I would like something faster. I stumbled upon the idea of ​​cloning IL and am trying to work with some code found here (Whizzo Blog) .

Actually, I am not getting IL yet, so I hope someone can help a little and explain some things to me (I think this is the first question of a few).

The question is here (and btw, if anyone has good links explaining opcodes and reflection.emit a bit more, which would be great, MSDN doesn't give much details), how are the values ​​copied? I see that a new object is being built and pushed out of the stack

generator.Emit(OpCodes.Newobj, cInfo); generator.Emit(OpCodes.Stloc, cloneVariable); 

Then a little later the set value of the field, the value of which is somehow copied. I do not understand how we return to the original object and evaluate it when the original object does not seem to be referenced? Or is this some kind of LocalBuilder magic (I'm not 100% sure what it does):

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

I changed the code a bit, because I always need a Deep clone, and I want it based on serialized fields:

 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); } 
0
source share
2 answers

First you have

 generator.Emit(OpCodes.Ldloc, cloneVariable); generator.Emit(OpCodes.Ldarg_0); 

Your stack contains (cloneVariable, myObject)

 enerator.Emit(OpCodes.Ldfld, field); 

This link refers to an object, pulls a value from a field, and pushes the value onto the stack

Your stack contains (cloneVariable, myObject.field)

 generator.Emit(OpCodes.Stfld, field); 

This object provides a reference to the object and the value and stores the value in the field of the object. The result is equivalent to C #

 cloneVariable.field = myObject.field 
+3
source

¿Will it not be easier to use structures instead of classes and directly build an array of type bytes in the new memory of the object?

I am not very sure if this can be done directly with Marshalling, but I almost - (always keep the door open to run away) - this can be done by compiling / insecurely, throwing a pointer to byte * and copy these bytes to the target pointer of the structure.

[Edit] Forget about pointers, you can do it without danger, just by sorting. Check out this post;

How to convert structure to byte array in C #?

[Edit2] I need a little patience: P your decision is much faster.

0
source

Source: https://habr.com/ru/post/1402136/


All Articles