Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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
                }
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
            }
        }
Esempio n. 8
0
        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);
        }