public void ShouldFindNoDifferences() { var obj = DynamicType.CreateClass("C", DynamicType.CreateClass("B", DynamicType.CreateClass("A"))).Instantiate(); var typeDescriptor = TypeDescriptor.CreateFromType(obj.GetType()); var compareResult = typeDescriptor.CompareWith(typeDescriptor); Assert.IsTrue(compareResult.Empty); }
private void GenerateUpdateStructFields(Type formalType, LocalBuilder structLocal) { var fields = TypeDescriptor.CreateFromType(formalType).FieldsToDeserialize; foreach (var field in fields) { if (field.Field == null) { GenerateReadField(field.TypeToOmit, false); generator.Emit(OpCodes.Pop); continue; } if (field.Field.IsDefined(typeof(TransientAttribute), false)) { if (field.Field.IsDefined(typeof(ConstructorAttribute), false)) { generator.Emit(OpCodes.Ldloca, structLocal); PushFieldInfoOntoStack(field.Field); GenerateCodeFCall <FieldInfo, object>(fi => { // this code is done using reflection and not generated due to // small estimated profit and lot of code to write: // * copying constructor attributes from generating to generated code // * calculating optimal constructor to call based on a collection of arguments var ctorAttribute = (ConstructorAttribute)fi.GetCustomAttributes(false).First(x => x is ConstructorAttribute); return(Activator.CreateInstance(fi.FieldType, ctorAttribute.Parameters)); }); if (field.Field.FieldType.IsValueType) { generator.Emit(OpCodes.Unbox_Any, field.Field.FieldType); } generator.Emit(OpCodes.Stfld, field.Field); } continue; } generator.Emit(OpCodes.Ldloca, structLocal); var type = field.TypeToOmit ?? field.Field.FieldType; GenerateReadField(type, false); if (field.Field != null) { generator.Emit(OpCodes.Stfld, field.Field); } else { generator.Emit(OpCodes.Pop); // struct local generator.Emit(OpCodes.Pop); // read value } } }
public void ShouldNotDetectInsertionOfTransientField() { var objPrev = DynamicType.CreateClass("A").Instantiate(); var objCurr = DynamicType.CreateClass("A").WithTransientField("a", typeof(int)).Instantiate(); var descPrev = TypeDescriptor.CreateFromType(objPrev.GetType()); var descCurr = TypeDescriptor.CreateFromType(objCurr.GetType()); var compareResult = descCurr.CompareWith(descPrev); Assert.IsTrue(compareResult.Empty); }
public void ShouldHandleAssemblyVersionChange() { var objPrev = DynamicType.CreateClass("A").WithField("a", DynamicType.CreateClass("C").WithField <int>("c")).Instantiate(new Version(1, 0)); var objCurr = DynamicType.CreateClass("A").WithField("a", DynamicType.CreateClass("C").WithField <int>("c")).Instantiate(new Version(1, 1)); var descPrev = TypeDescriptor.CreateFromType(objPrev.GetType()); var descCurr = TypeDescriptor.CreateFromType(objCurr.GetType()); var compareResult = descCurr.CompareWith(descPrev, VersionToleranceLevel.AllowAssemblyVersionChange); Assert.IsEmpty(compareResult.FieldsAdded); Assert.IsEmpty(compareResult.FieldsChanged); Assert.IsEmpty(compareResult.FieldsRemoved); }
public void ShouldDetectInsertionOfOverridingField() { var objPrev = DynamicType.CreateClass("A", DynamicType.CreateClass("Base").WithField("a", typeof(int))).Instantiate(); var objCurr = DynamicType.CreateClass("A", DynamicType.CreateClass("Base").WithField("a", typeof(int))).WithField("a", typeof(int)).Instantiate(); var descPrev = TypeDescriptor.CreateFromType(objPrev.GetType()); var descCurr = TypeDescriptor.CreateFromType(objCurr.GetType()); var compareResult = descCurr.CompareWith(descPrev); Assert.IsEmpty(compareResult.FieldsRemoved); Assert.IsEmpty(compareResult.FieldsChanged); Assert.AreEqual(1, compareResult.FieldsAdded.Count); Assert.AreEqual("A:a", compareResult.FieldsAdded[0].FullName); }
public void ShouldDetectFieldTypeChange() { var objPrev = DynamicType.CreateClass("A").WithField("a", typeof(int)).Instantiate(); var objCurr = DynamicType.CreateClass("A").WithField("a", typeof(long)).Instantiate(); var descPrev = TypeDescriptor.CreateFromType(objPrev.GetType()); var descCurr = TypeDescriptor.CreateFromType(objCurr.GetType()); var compareResult = descCurr.CompareWith(descPrev); Assert.IsEmpty(compareResult.FieldsAdded); Assert.IsEmpty(compareResult.FieldsRemoved); Assert.AreEqual(1, compareResult.FieldsChanged.Count); Assert.AreEqual("A:a", compareResult.FieldsChanged.ElementAt(0).FullName); }
private void GenerateUpdateFields(Type formalType, LocalBuilder objectIdLocal) { var fields = TypeDescriptor.CreateFromType(formalType).FieldsToDeserialize; foreach (var fieldOrType in fields) { if (fieldOrType.Field == null) { GenerateReadField(fieldOrType.TypeToOmit, false); generator.Emit(OpCodes.Pop); continue; } var field = fieldOrType.Field; if (field.IsDefined(typeof(TransientAttribute), false)) { if (field.IsDefined(typeof(ConstructorAttribute), false)) { PushFieldInfoOntoStack(field); PushDeserializedObjectOntoStack(objectIdLocal); GenerateCodeCall <FieldInfo, object>((fi, target) => { // this code is done using reflection and not generated due to // small estimated profit and lot of code to write: // * copying constructor attributes from generating to generated code // * calculating optimal constructor to call based on a collection of arguments var ctorAttribute = (ConstructorAttribute)fi.GetCustomAttributes(false).First(x => x is ConstructorAttribute); fi.SetValue(target, Activator.CreateInstance(fi.FieldType, ctorAttribute.Parameters)); }); } continue; } PushDeserializedObjectOntoStack(objectIdLocal); generator.Emit(OpCodes.Castclass, field.ReflectedType); GenerateReadField(field.FieldType, false); generator.Emit(OpCodes.Stfld, field); } }
internal WriteMethodGenerator(Type typeToGenerate, bool treatCollectionAsUserObject, int surrogateId, FieldInfo typeIndicesField, FieldInfo surrogatesField, FieldInfo typeIdWrittenField, MethodInfo writeObjectMethod) { typeWeAreGeneratingFor = typeToGenerate; ObjectWriter.CheckLegality(typeToGenerate); InitializeMethodInfos(); if (!typeToGenerate.IsArray) { dynamicMethod = new DynamicMethod(string.Format("Write_{0}", typeToGenerate.Name), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), ParameterTypes, typeToGenerate, true); } else { var methodNo = Interlocked.Increment(ref WriteArrayMethodCounter); dynamicMethod = new DynamicMethod(string.Format("WriteArray{0}_{1}", methodNo, typeToGenerate.Name), null, ParameterTypes, true); } generator = dynamicMethod.GetILGenerator(); // surrogates if (surrogateId != -1) { generator.Emit(OpCodes.Ldarg_0); // used (1) // obtain surrogate factory generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, surrogatesField); generator.Emit(OpCodes.Ldc_I4, surrogateId); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <InheritanceAwareList <Delegate> >(x => x.GetByIndex(0))); // call surrogate factory to obtain surrogate object var delegateType = typeof(Func <,>).MakeGenericType(typeToGenerate, typeof(object)); generator.Emit(OpCodes.Castclass, delegateType); generator.Emit(OpCodes.Ldarg_2); generator.Emit(OpCodes.Call, delegateType.GetMethod("Invoke")); // jump to surrogate serialization generator.Emit(OpCodes.Call, writeObjectMethod); // (1) here generator.Emit(OpCodes.Ret); return; } generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, typeIdWrittenField); var omitWriteIdLabel = generator.DefineLabel(); generator.Emit(OpCodes.Brtrue, omitWriteIdLabel); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, typeIndicesField); generator.Emit(OpCodes.Ldtoken, typeToGenerate); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <RuntimeTypeHandle, Type>(o => Type.GetTypeFromHandle(o))); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo(() => TypeDescriptor.CreateFromType(null))); generator.Emit(OpCodes.Call, typeof(Dictionary <TypeDescriptor, int>).GetMethod("get_Item")); generator.Emit(OpCodes.Call, Helpers.GetMethodInfo <PrimitiveWriter>(x => x.Write(0))); generator.MarkLabel(omitWriteIdLabel); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4_0); generator.Emit(OpCodes.Stfld, typeIdWrittenField); // preserialization callbacks GenerateInvokeCallback(typeToGenerate, typeof(PreSerializationAttribute)); var exceptionBlockNeeded = Helpers.GetMethodsWithAttribute(typeof(PostSerializationAttribute), typeToGenerate).Any() || Helpers.GetMethodsWithAttribute(typeof(LatePostSerializationAttribute), typeToGenerate).Any(); if (exceptionBlockNeeded) { generator.BeginExceptionBlock(); } if (!GenerateSpecialWrite(typeToGenerate, treatCollectionAsUserObject)) { GenerateWriteFields(gen => { gen.Emit(OpCodes.Ldarg_2); }, typeToGenerate); } if (exceptionBlockNeeded) { generator.BeginFinallyBlock(); } // postserialization callbacks GenerateInvokeCallback(typeToGenerate, typeof(PostSerializationAttribute)); GenerateAddCallbackToInvokeList(typeToGenerate, typeof(LatePostSerializationAttribute)); if (exceptionBlockNeeded) { generator.EndExceptionBlock(); } generator.Emit(OpCodes.Ret); }