예제 #1
1
        /// <summary>
        /// Transform open generic types to closed instantiation using context information.
        /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
        /// </summary>
        public static TypeReference Process(TypeReference context, TypeReference type)
        {
            if (type == null)
                return null;

            var genericInstanceTypeContext = context as GenericInstanceType;
            if (genericInstanceTypeContext == null)
                return type;

            if (genericInstanceTypeContext.ContainsGenericParameter())
                return type;

            // Build dictionary that will map generic type to their real implementation type
            var resolvedType = context.Resolve();
            var genericTypeMapping = new Dictionary<TypeReference, TypeReference>();
            for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
            {
                var genericParameter = context.GetElementType().Resolve().GenericParameters[i];
                genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
            }

            var visitor = new ResolveGenericsVisitor(genericTypeMapping);
            var result = visitor.VisitDynamic(type);

            // Make sure type is closed now
            if (result.ContainsGenericParameter())
                throw new InvalidOperationException("Unsupported generic resolution.");

            return result;
        }
예제 #2
0
        public static void InflateGenericType(TypeDefinition genericType, TypeDefinition inflatedType, params TypeReference[] genericTypes)
        {
            // Base type
            var genericMapping = new Dictionary <TypeReference, TypeReference>();

            for (int i = 0; i < genericTypes.Length; ++i)
            {
                genericMapping.Add(genericType.GenericParameters[i], genericTypes[i]);
            }

            var resolveGenericsVisitor = new ResolveGenericsVisitor(genericMapping);

            inflatedType.BaseType = inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(genericType.BaseType));

            // Some stuff are not handled yet
            if (genericType.HasNestedTypes)
            {
                throw new NotImplementedException();
            }

            foreach (var field in genericType.Fields)
            {
                var clonedField = new FieldDefinition(field.Name, field.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(field.FieldType)));
                inflatedType.Fields.Add(clonedField);
            }

            foreach (var property in genericType.Properties)
            {
                if (property.HasParameters)
                {
                    throw new NotImplementedException();
                }

                var clonedProperty = new PropertyDefinition(property.Name, property.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(property.PropertyType)))
                {
                    HasThis   = property.HasThis,
                    GetMethod = property.GetMethod != null?InflateMethod(inflatedType, property.GetMethod, resolveGenericsVisitor) : null,
                                    SetMethod = property.SetMethod != null?InflateMethod(inflatedType, property.GetMethod, resolveGenericsVisitor) : null,
                };

                inflatedType.Properties.Add(clonedProperty);
            }

            // Clone methods
            foreach (var method in genericType.Methods)
            {
                var clonedMethod = InflateMethod(inflatedType, method, resolveGenericsVisitor);
                inflatedType.Methods.Add(clonedMethod);
            }
        }
        public static IEnumerable <SerializableItem> GetSerializableItems(TypeReference type, bool serializeFields, ComplexTypeSerializerFlags?flagsOverride = null)
        {
            foreach (var serializableItemOriginal in GetSerializableItems(type.Resolve(), serializeFields, flagsOverride))
            {
                var serializableItem = serializableItemOriginal;

                // Try to resolve open generic types with context to have closed types.
                if (serializableItem.Type.ContainsGenericParameter())
                {
                    serializableItem.Type = ResolveGenericsVisitor.Process(type, serializableItem.Type);
                }

                yield return(serializableItem);
            }
        }
예제 #4
0
        /// <summary>
        /// Transform open generic types to closed instantiation using context information.
        /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
        /// </summary>
        public static TypeReference Process(TypeReference context, TypeReference type)
        {
            if (type == null)
            {
                return(null);
            }

            var genericInstanceTypeContext = context as GenericInstanceType;

            if (genericInstanceTypeContext == null)
            {
                return(type);
            }

            if (genericInstanceTypeContext.ContainsGenericParameter())
            {
                return(type);
            }

            // Build dictionary that will map generic type to their real implementation type
            var resolvedType       = context.Resolve();
            var genericTypeMapping = new Dictionary <TypeReference, TypeReference>();

            for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
            {
                var genericParameter = context.GetElementType().Resolve().GenericParameters[i];
                genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
            }

            var visitor = new ResolveGenericsVisitor(genericTypeMapping);
            var result  = visitor.VisitDynamic(type);

            // Make sure type is closed now
            if (result.ContainsGenericParameter())
            {
                throw new InvalidOperationException("Unsupported generic resolution.");
            }

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\r\n");

            #line 7 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"

            var className  = SerializerTypeName(type, true, true);
            var parentType = hasParentSerializer ? ResolveGenericsVisitor.Process(type, type.BaseType) : null;


            #line default
            #line hidden
            this.Write("\r\nnamespace SiliconStudio.DataSerializers\r\n{\r\n\t");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            if (type.HasGenericParameters)
            {
            #line default
            #line hidden
                this.Write("public ");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }

            #line default
            #line hidden
            this.Write("sealed class ");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(className));

            #line default
            #line hidden
            this.Write(" : ");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(type.IsClass && !type.IsValueType && !type.IsAbstract && HasEmptyConstructor(type) ? "Class" : string.Empty));

            #line default
            #line hidden
            this.Write("DataSerializer<");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(type.ConvertCSharp()));

            #line default
            #line hidden
            this.Write(">, IDataSerializerInitializer");

            #line 14 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(GenerateGenericConstraints(type)));

            #line default
            #line hidden
            this.Write("\r\n\t{\r\n");

            #line 16 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            if (hasParentSerializer)
            {
            #line default
            #line hidden
                this.Write("\t\tprivate DataSerializer<");

            #line 17 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(parentType.ConvertCSharp()));

            #line default
            #line hidden
                this.Write("> parentSerializer;\r\n");

            #line 18 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }
            var serializableItems = GetSerializableItems(type, true).ToArray();


            #line default
            #line hidden

            #line 21 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            foreach (var serializableItem in serializableItems)
            {
            #line default
            #line hidden
                this.Write("\t\tprivate DataSerializer<");

            #line 22 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(serializableItem.Type.ConvertCSharp()));

            #line default
            #line hidden
                this.Write("> ");

            #line 22 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(serializableItem.MemberInfo.Name));

            #line default
            #line hidden
                this.Write("Serializer;\r\n");

            #line 23 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }

            #line default
            #line hidden
            this.Write("\r\n\t\tpublic void Initialize(SerializerSelector serializerSelector)\r\n\t\t{\r\n");

            #line 27 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            if (hasParentSerializer)
            {
            #line default
            #line hidden
                this.Write("\t\t\t// Get parent serializer\r\n\t\t\tparentSerializer = serializerSelector.GetSerializ" +
                           "er<");

            #line 29 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(parentType.ConvertCSharp()));

            #line default
            #line hidden
                this.Write(">();\r\n\t\t\tif (parentSerializer == null)\r\n\t\t\t\tthrow new InvalidOperationException(s" +
                           "tring.Format(\"Could not find parent serializer for type {0}\", @\"");

            #line 31 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(parentType.ConvertCSharp()));

            #line default
            #line hidden
                this.Write("\"));\r\n");

            #line 32 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }

            #line default
            #line hidden
            this.Write("\t\t\t// Cache member serializers\r\n");

            #line 34 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            foreach (var serializableItem in serializableItems)
            {
            #line default
            #line hidden
                this.Write("\t\t\t");

            #line 35 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(serializableItem.MemberInfo.Name));

            #line default
            #line hidden
                this.Write("Serializer = MemberSerializer<");

            #line 35 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(serializableItem.Type.ConvertCSharp()));

            #line default
            #line hidden
                this.Write(">.Create(serializerSelector);\r\n");

            #line 36 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }

            #line default
            #line hidden
            this.Write("\t\t}\r\n\r\n\t\tpublic override void Serialize(ref ");

            #line 39 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(type.ConvertCSharp()));

            #line default
            #line hidden
            this.Write(" obj, ArchiveMode mode, SerializationStream stream)\r\n\t\t{\r\n");

            #line 41 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            if (hasParentSerializer)
            {
            #line default
            #line hidden
                this.Write("\t\t\t// Serialize parent (for now we don\'t copy reference back because it shouldn\'t" +
                           " change)\r\n\t\t\t");

            #line 43 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(parentType.ConvertCSharp()));

            #line default
            #line hidden
                this.Write(" parentObj = obj;\r\n\t\t\tparentSerializer.Serialize(ref parentObj, mode, stream);\r\n\t" +
                           "\t\tobj = (");

            #line 45 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(type.ConvertCSharp()));

            #line default
            #line hidden
                this.Write(")parentObj;\r\n\r\n");

            #line 47 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }
            foreach (var serializableItem in serializableItems)
            {
                var memberType         = serializableItem.Type;
                var memberTypeName     = serializableItem.Type.ConvertCSharp();
                var memberName         = serializableItem.MemberInfo.Name;
                var memberAssignBack   = serializableItem.AssignBack;
                var memberVariableName = (serializableItem.MemberInfo is PropertyDefinition || !memberAssignBack) ? CreateMemberVariableName(serializableItem.MemberInfo) : null;
                var memberAccessName   = memberVariableName != null ? memberVariableName : "obj." + memberName;

                if (serializableItem.HasFixedAttribute)
                {
            #line default
            #line hidden
                    this.Write("\t\tthrow new NotImplementedException(\"FixedBuffer attribute is not supported.\");\r\n" +
                               "");

            #line 59 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                }
                else
                {
                    if (memberVariableName != null)
                    {
            #line default
            #line hidden
                        this.Write("            ");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        this.Write(this.ToStringHelper.ToStringWithCulture(memberTypeName));

            #line default
            #line hidden
                        this.Write(" ");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        this.Write(this.ToStringHelper.ToStringWithCulture(memberVariableName));

            #line default
            #line hidden
                        this.Write(" = ");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        if (memberAssignBack)
                        {
            #line default
            #line hidden
                            this.Write("mode == ArchiveMode.Serialize ? obj.");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                            this.Write(this.ToStringHelper.ToStringWithCulture(memberName));

            #line default
            #line hidden
                            this.Write(" : default(");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                            this.Write(this.ToStringHelper.ToStringWithCulture(memberTypeName));

            #line default
            #line hidden
                            this.Write(")");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        }
                        else
                        {
            #line default
            #line hidden
                            this.Write("obj.");

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                            this.Write(this.ToStringHelper.ToStringWithCulture(memberName));

            #line default
            #line hidden

            #line 64 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        }

            #line default
            #line hidden
                        this.Write(";\r\n");

            #line 65 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                    }

            #line default
            #line hidden
                    this.Write("            ");

            #line 66 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                    this.Write(this.ToStringHelper.ToStringWithCulture(serializableItem.MemberInfo.Name));

            #line default
            #line hidden
                    this.Write("Serializer.Serialize(ref ");

            #line 66 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                    this.Write(this.ToStringHelper.ToStringWithCulture(memberAccessName));

            #line default
            #line hidden
                    this.Write(", mode, stream);\r\n");

            #line 67 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                    if (memberVariableName != null && memberAssignBack)
                    {
            #line default
            #line hidden
                        this.Write("            obj.");

            #line 69 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        this.Write(this.ToStringHelper.ToStringWithCulture(memberName));

            #line default
            #line hidden
                        this.Write(" = ");

            #line 69 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                        this.Write(this.ToStringHelper.ToStringWithCulture(memberVariableName));

            #line default
            #line hidden
                        this.Write(";\r\n");

            #line 70 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                    }
                }
            }

            #line default
            #line hidden
            this.Write("\t\t}\r\n\r\n\t\tinternal static void ForceGenericInstantiation()\r\n\t\t{\r\n");

            #line 77 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"

            foreach (var memberSerializerType in EnumerateSerializerTypes(serializableItems.Select(x => x.Type)))
            {
            #line default
            #line hidden
                this.Write("\t\t\ttypeof(");

            #line 79 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
                this.Write(this.ToStringHelper.ToStringWithCulture(memberSerializerType.ConvertCSharp()));

            #line default
            #line hidden
                this.Write(").ToString();\r\n");

            #line 80 "C:\DEV\paradox\sources\common\core\SiliconStudio.AssemblyProcessor.Common\ComplexClassSerializerGenerator.tt"
            }

            #line default
            #line hidden
            this.Write("\t\t}\r\n\t}\r\n}");
            return(this.GenerationEnvironment.ToString());
        }
예제 #6
0
        public void ProcessSerializers(CecilSerializerContext context)
        {
            var references = new HashSet <AssemblyDefinition>();

            EnumerateReferences(references, context.Assembly);

            var coreAssembly = CecilExtensions.FindCorlibAssembly(context.Assembly);

            // Only process assemblies depending on Xenko.Engine
            if (!references.Any(x => x.Name.Name == "SiliconStudio.Xenko.Engine"))
            {
                // Make sure Xenko.Engine.Serializers can access everything internally
                var internalsVisibleToAttribute = coreAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                var serializationAssemblyName   = "SiliconStudio.Xenko.Engine.Serializers";

                // Add [InteralsVisibleTo] attribute
                var internalsVisibleToAttributeCtor = context.Assembly.MainModule.ImportReference(internalsVisibleToAttribute.GetConstructors().Single());
                var internalsVisibleAttribute       = new CustomAttribute(internalsVisibleToAttributeCtor)
                {
                    ConstructorArguments =
                    {
                        new CustomAttributeArgument(context.Assembly.MainModule.ImportReference(context.Assembly.MainModule.TypeSystem.String), serializationAssemblyName)
                    }
                };
                context.Assembly.CustomAttributes.Add(internalsVisibleAttribute);

                return;
            }

            // Get or create method
            var updateEngineType  = GetOrCreateUpdateType(context.Assembly, true);
            var mainPrepareMethod = new MethodDefinition("UpdateMain", MethodAttributes.HideBySig | MethodAttributes.Assembly | MethodAttributes.Static, context.Assembly.MainModule.TypeSystem.Void);

            updateEngineType.Methods.Add(mainPrepareMethod);

            // Get some useful Cecil objects from SiliconStudio.Core
            var siliconStudioCoreAssembly = context.Assembly.Name.Name == "SiliconStudio.Core"
                    ? context.Assembly
                    : context.Assembly.MainModule.AssemblyResolver.Resolve("SiliconStudio.Core");
            var siliconStudioCoreModule = siliconStudioCoreAssembly.MainModule;

            var siliconStudioXenkoEngineAssembly = context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine"
                    ? context.Assembly
                    : context.Assembly.MainModule.AssemblyResolver.Resolve("SiliconStudio.Xenko.Engine");
            var siliconStudioXenkoEngineModule = siliconStudioXenkoEngineAssembly.MainModule;

            // Generate IL for SiliconStudio.Core
            if (context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine")
            {
                ProcessXenkoEngineAssembly(context);
            }
            else
            {
#if true || SILICONSTUDIO_XENKO_XAMARIN_CALLI_BUG
                // We still process UpdatableProperty<T> since we had to revert it back when writing back Xenko.Engine (otherwise it crashes at AOT on iOS)
                new UpdatablePropertyCodeGenerator(siliconStudioXenkoEngineAssembly).GenerateUpdatablePropertyCode();
#endif
            }

            animationDataType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Animations.AnimationData`1");

            var updatableFieldGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatableField`1");
            updatableFieldGenericCtor = updatableFieldGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            updatablePropertyGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatableProperty`1");
            updatablePropertyGenericCtor = updatablePropertyGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatablePropertyObjectGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdatablePropertyObject`1");
            updatablePropertyObjectGenericCtor = updatablePropertyObjectGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatableListUpdateResolverGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.ListUpdateResolver`1");
            updatableListUpdateResolverGenericCtor = updatableListUpdateResolverGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var updatableArrayUpdateResolverGenericType = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.ArrayUpdateResolver`1");
            updatableArrayUpdateResolverGenericCtor = updatableArrayUpdateResolverGenericType.Methods.First(x => x.IsConstructor && !x.IsStatic);

            var registerMemberMethod = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdateEngine").Methods.First(x => x.Name == "RegisterMember");
            var pclVisitor           = new PclFixupTypeVisitor(coreAssembly);
            pclVisitor.VisitMethod(registerMemberMethod);
            updateEngineRegisterMemberMethod = context.Assembly.MainModule.ImportReference(registerMemberMethod);

            var registerMemberResolverMethod = siliconStudioXenkoEngineModule.GetType("SiliconStudio.Xenko.Updater.UpdateEngine").Methods.First(x => x.Name == "RegisterMemberResolver");
            pclVisitor.VisitMethod(registerMemberResolverMethod);
            updateEngineRegisterMemberResolverMethod = context.Assembly.MainModule.ImportReference(registerMemberResolverMethod);

            var typeType = coreAssembly.MainModule.GetTypeResolved(typeof(Type).FullName);
            getTypeFromHandleMethod = context.Assembly.MainModule.ImportReference(typeType.Methods.First(x => x.Name == "GetTypeFromHandle"));

            // Make sure it is called at module startup
            var moduleInitializerAttribute = siliconStudioCoreModule.GetType("SiliconStudio.Core.ModuleInitializerAttribute");
            var ctorMethod = moduleInitializerAttribute.GetConstructors().Single(x => !x.IsStatic && !x.HasParameters);
            pclVisitor.VisitMethod(ctorMethod);
            mainPrepareMethod.CustomAttributes.Add(new CustomAttribute(context.Assembly.MainModule.ImportReference(ctorMethod)));

            // Emit serialization code for all the types we care about
            var processedTypes = new HashSet <TypeDefinition>(TypeReferenceEqualityComparer.Default);
            foreach (var serializableType in context.SerializableTypesProfiles.SelectMany(x => x.Value.SerializableTypes))
            {
                // Special case: when processing Xenko.Engine assembly, we automatically add dependent assemblies types too
                if (!serializableType.Value.Local && siliconStudioXenkoEngineAssembly != context.Assembly)
                {
                    continue;
                }

                var typeDefinition = serializableType.Key as TypeDefinition;
                if (typeDefinition == null)
                {
                    continue;
                }

                // Ignore already processed types
                if (!processedTypes.Add(typeDefinition))
                {
                    continue;
                }

                try
                {
                    ProcessType(context, typeDefinition, mainPrepareMethod);
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException(string.Format("Error when generating update engine code for {0}", typeDefinition), e);
                }
            }

            // Force generic instantiations
            var il = mainPrepareMethod.Body.GetILProcessor();
            foreach (var serializableType in context.SerializableTypesProfiles.SelectMany(x => x.Value.SerializableTypes).ToArray())
            {
                // Special case: when processing Xenko.Engine assembly, we automatically add dependent assemblies types too
                if (!serializableType.Value.Local && siliconStudioXenkoEngineAssembly != context.Assembly)
                {
                    continue;
                }

                // Make sure AnimationData<T> is serializable
                //if (serializableType.Value.Mode == DataSerializerGenericMode.None)
                //    context.GenerateSerializer(context.Assembly.MainModule.ImportReference(animationDataType).MakeGenericType(context.Assembly.MainModule.ImportReference(serializableType.Key)));

                // Try to find if original method definition was generated
                var typeDefinition = serializableType.Key.Resolve();

                // If using List<T>, register this type in UpdateEngine
                var listInterfaceType = typeDefinition.Interfaces.OfType <GenericInstanceType>().FirstOrDefault(x => x.ElementType.FullName == typeof(IList <>).FullName);
                if (listInterfaceType != null)
                {
                    //call Updater.UpdateEngine.RegisterMemberResolver(new Updater.ListUpdateResolver<T>());
                    var elementType = ResolveGenericsVisitor.Process(serializableType.Key, listInterfaceType.GenericArguments[0]);
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableListUpdateResolverGenericCtor).MakeGeneric(context.Assembly.MainModule.ImportReference(elementType).FixupValueType()));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberResolverMethod);
                }

                // Same for arrays
                var arrayType = serializableType.Key as ArrayType;
                if (arrayType != null)
                {
                    //call Updater.UpdateEngine.RegisterMemberResolver(new Updater.ArrayUpdateResolver<T>());
                    var elementType = ResolveGenericsVisitor.Process(serializableType.Key, arrayType.ElementType);
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableArrayUpdateResolverGenericCtor).MakeGeneric(context.Assembly.MainModule.ImportReference(elementType).FixupValueType()));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberResolverMethod);
                }

                var genericInstanceType = serializableType.Key as GenericInstanceType;
                if (genericInstanceType != null)
                {
                    var expectedUpdateMethodName = ComputeUpdateMethodName(typeDefinition);
                    var updateMethod             = GetOrCreateUpdateType(typeDefinition.Module.Assembly, false)?.Methods.FirstOrDefault(x => x.Name == expectedUpdateMethodName && x.HasGenericParameters && x.GenericParameters.Count == genericInstanceType.GenericParameters.Count);

                    // If nothing was found in main assembly, also look in SiliconStudio.Xenko.Engine assembly, just in case (it might defines some shared/corlib types -- currently not the case)
                    if (updateMethod == null)
                    {
                        updateMethod = GetOrCreateUpdateType(siliconStudioXenkoEngineAssembly, false)?.Methods.FirstOrDefault(x => x.Name == expectedUpdateMethodName && x.HasGenericParameters && x.GenericParameters.Count == genericInstanceType.GenericParameters.Count);
                    }

                    if (updateMethod != null)
                    {
                        // Emit call to update engine setup method with generic arguments of current type
                        il.Emit(OpCodes.Call, context.Assembly.MainModule.ImportReference(updateMethod)
                                .MakeGenericMethod(genericInstanceType.GenericArguments
                                                   .Select(context.Assembly.MainModule.ImportReference)
                                                   .Select(CecilExtensions.FixupValueType).ToArray()));
                    }
                }
            }

            il.Emit(OpCodes.Ret);

#if true || SILICONSTUDIO_XENKO_XAMARIN_CALLI_BUG
            // Due to Xamarin iOS AOT limitation, we can't keep this type around because it fails compilation
            if (context.Assembly.Name.Name == "SiliconStudio.Xenko.Engine")
            {
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "GetStructAndUnbox"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "GetBlittable"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "SetStruct"));
                NotImplementedBody(updatablePropertyGenericType.Methods.First(x => x.Name == "SetBlittable"));
            }
#endif
        }
예제 #7
0
        public void ProcessType(CecilSerializerContext context, TypeReference type, MethodDefinition updateMainMethod)
        {
            var typeDefinition = type.Resolve();

            // No need to process enum
            if (typeDefinition.IsEnum)
            {
                return;
            }

            var updateCurrentMethod = updateMainMethod;
            ResolveGenericsVisitor replaceGenericsVisitor = null;

            if (typeDefinition.HasGenericParameters)
            {
                // Make a prepare method for just this object since it might need multiple instantiation
                updateCurrentMethod = new MethodDefinition(ComputeUpdateMethodName(typeDefinition), MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, context.Assembly.MainModule.TypeSystem.Void);
                var genericsMapping = new Dictionary <TypeReference, TypeReference>();
                foreach (var genericParameter in typeDefinition.GenericParameters)
                {
                    var genericParameterCopy = new GenericParameter(genericParameter.Name, updateCurrentMethod)
                    {
                        Attributes = genericParameter.Attributes,
                    };
                    foreach (var constraint in genericParameter.Constraints)
                    {
                        genericParameterCopy.Constraints.Add(context.Assembly.MainModule.ImportReference(constraint));
                    }
                    updateCurrentMethod.GenericParameters.Add(genericParameterCopy);

                    genericsMapping[genericParameter] = genericParameterCopy;
                }

                replaceGenericsVisitor = new ResolveGenericsVisitor(genericsMapping);

                updateMainMethod.DeclaringType.Methods.Add(updateCurrentMethod);
            }

            var il = updateCurrentMethod.Body.GetILProcessor();
            var emptyObjectField = updateMainMethod.DeclaringType.Fields.FirstOrDefault(x => x.Name == "emptyObject");

            // Note: forcing fields and properties to be processed in all cases
            foreach (var serializableItem in ComplexClassSerializerGenerator.GetSerializableItems(type, true, ComplexTypeSerializerFlags.SerializePublicFields | ComplexTypeSerializerFlags.SerializePublicProperties | ComplexTypeSerializerFlags.Updatable))
            {
                var fieldReference = serializableItem.MemberInfo as FieldReference;
                if (fieldReference != null)
                {
                    var field = fieldReference.Resolve();

                    // First time it is needed, let's create empty object: var emptyObject = new object();
                    if (emptyObjectField == null)
                    {
                        emptyObjectField = new FieldDefinition("emptyObject", FieldAttributes.Static | FieldAttributes.Private, context.Assembly.MainModule.TypeSystem.Object);

                        // Create static ctor that will initialize this object
                        var staticConstructor = new MethodDefinition(".cctor",
                                                                     MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                                     context.Assembly.MainModule.TypeSystem.Void);
                        var staticConstructorIL = staticConstructor.Body.GetILProcessor();
                        staticConstructorIL.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(emptyObjectField.FieldType.Resolve().GetConstructors().Single(x => !x.IsStatic && !x.HasParameters)));
                        staticConstructorIL.Emit(OpCodes.Stsfld, emptyObjectField);
                        staticConstructorIL.Emit(OpCodes.Ret);

                        updateMainMethod.DeclaringType.Fields.Add(emptyObjectField);
                        updateMainMethod.DeclaringType.Methods.Add(staticConstructor);
                    }

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, field.Name);

                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Ldflda, context.Assembly.MainModule.ImportReference(fieldReference));
                    il.Emit(OpCodes.Conv_I);
                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Conv_I);
                    il.Emit(OpCodes.Sub);
                    il.Emit(OpCodes.Conv_I4);

                    var fieldType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(field.FieldType) : field.FieldType).FixupValueType();
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableFieldGenericCtor).MakeGeneric(fieldType));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }

                var propertyReference = serializableItem.MemberInfo as PropertyReference;
                if (propertyReference != null)
                {
                    var property = propertyReference.Resolve();

                    var propertyGetMethod = context.Assembly.MainModule.ImportReference(property.GetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, property.Name);

                    il.Emit(OpCodes.Ldftn, propertyGetMethod);

                    // Only get setter if it exists and it's public
                    if (property.SetMethod != null && property.SetMethod.IsPublic)
                    {
                        var propertySetMethod = context.Assembly.MainModule.ImportReference(property.SetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());
                        il.Emit(OpCodes.Ldftn, propertySetMethod);
                    }
                    else
                    {
                        // 0 (native int)
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Conv_I);
                    }

                    var propertyType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(property.PropertyType) : property.PropertyType).FixupValueType();

                    var updatablePropertyInflatedCtor = GetOrCreateUpdatablePropertyCtor(context.Assembly, propertyType);

                    il.Emit(OpCodes.Newobj, updatablePropertyInflatedCtor);
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }
            }

            if (updateCurrentMethod != updateMainMethod)
            {
                // If we have a local method, close it
                il.Emit(OpCodes.Ret);

                // Also call it from main method if it was a closed generic instantiation
                if (type is GenericInstanceType)
                {
                    il = updateMainMethod.Body.GetILProcessor();
                    il.Emit(OpCodes.Call, updateCurrentMethod.MakeGeneric(((GenericInstanceType)type).GenericArguments.Select(context.Assembly.MainModule.ImportReference).Select(CecilExtensions.FixupValueType).ToArray()));
                }
            }
        }
예제 #8
0
        public void ProcessType(CecilSerializerContext context, TypeReference type, MethodDefinition updateMainMethod)
        {
            var typeDefinition = type.Resolve();

            // No need to process enum
            if (typeDefinition.IsEnum)
                return;

            var updateCurrentMethod = updateMainMethod;
            ResolveGenericsVisitor replaceGenericsVisitor = null;

            if (typeDefinition.HasGenericParameters)
            {
                // Make a prepare method for just this object since it might need multiple instantiation
                updateCurrentMethod = new MethodDefinition(ComputeUpdateMethodName(typeDefinition), MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, context.Assembly.MainModule.TypeSystem.Void);
                var genericsMapping = new Dictionary<TypeReference, TypeReference>();
                foreach (var genericParameter in typeDefinition.GenericParameters)
                {
                    var genericParameterCopy = new GenericParameter(genericParameter.Name, updateCurrentMethod)
                    {
                        Attributes = genericParameter.Attributes,
                    };
                    foreach (var constraint in genericParameter.Constraints)
                        genericParameterCopy.Constraints.Add(context.Assembly.MainModule.ImportReference(constraint));
                    updateCurrentMethod.GenericParameters.Add(genericParameterCopy);

                    genericsMapping[genericParameter] = genericParameterCopy;
                }

                replaceGenericsVisitor = new ResolveGenericsVisitor(genericsMapping);

                updateMainMethod.DeclaringType.Methods.Add(updateCurrentMethod);
            }

            var il = updateCurrentMethod.Body.GetILProcessor();
            var emptyObjectField = updateMainMethod.DeclaringType.Fields.FirstOrDefault(x => x.Name == "emptyObject");

            // Note: forcing fields and properties to be processed in all cases
            foreach (var serializableItem in ComplexClassSerializerGenerator.GetSerializableItems(type, true, ComplexTypeSerializerFlags.SerializePublicFields | ComplexTypeSerializerFlags.SerializePublicProperties | ComplexTypeSerializerFlags.Updatable))
            {
                var fieldReference = serializableItem.MemberInfo as FieldReference;
                if (fieldReference != null)
                {
                    var field = fieldReference.Resolve();

                    // First time it is needed, let's create empty object: var emptyObject = new object();
                    if (emptyObjectField == null)
                    {
                        emptyObjectField = new FieldDefinition("emptyObject", FieldAttributes.Static | FieldAttributes.Private, context.Assembly.MainModule.TypeSystem.Object);

                        // Create static ctor that will initialize this object
                        var staticConstructor = new MethodDefinition(".cctor",
                                                MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                                                context.Assembly.MainModule.TypeSystem.Void);
                        var staticConstructorIL = staticConstructor.Body.GetILProcessor();
                        staticConstructorIL.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(emptyObjectField.FieldType.Resolve().GetConstructors().Single(x => !x.IsStatic && !x.HasParameters)));
                        staticConstructorIL.Emit(OpCodes.Stsfld, emptyObjectField);
                        staticConstructorIL.Emit(OpCodes.Ret);

                        updateMainMethod.DeclaringType.Fields.Add(emptyObjectField);
                        updateMainMethod.DeclaringType.Methods.Add(staticConstructor);
                    }

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, field.Name);

                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Ldflda, context.Assembly.MainModule.ImportReference(fieldReference));
                    il.Emit(OpCodes.Ldsfld, emptyObjectField);
                    il.Emit(OpCodes.Conv_I);
                    il.Emit(OpCodes.Sub);
                    il.Emit(OpCodes.Conv_I4);

                    var fieldType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(field.FieldType) : field.FieldType).FixupValueType();
                    il.Emit(OpCodes.Newobj, context.Assembly.MainModule.ImportReference(updatableFieldGenericCtor).MakeGeneric(fieldType));
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }

                var propertyReference = serializableItem.MemberInfo as PropertyReference;
                if (propertyReference != null)
                {
                    var property = propertyReference.Resolve();

                    var propertyGetMethod = context.Assembly.MainModule.ImportReference(property.GetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());

                    il.Emit(OpCodes.Ldtoken, type);
                    il.Emit(OpCodes.Call, getTypeFromHandleMethod);
                    il.Emit(OpCodes.Ldstr, property.Name);

                    il.Emit(OpCodes.Ldftn, propertyGetMethod);

                    // Only get setter if it exists and it's public
                    if (property.SetMethod != null && property.SetMethod.IsPublic)
                    {
                        var propertySetMethod = context.Assembly.MainModule.ImportReference(property.SetMethod).MakeGeneric(updateCurrentMethod.GenericParameters.ToArray());
                        il.Emit(OpCodes.Ldftn, propertySetMethod);
                    }
                    else
                    {
                        // 0 (native int)
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Conv_I);
                    }

                    var propertyType = context.Assembly.MainModule.ImportReference(replaceGenericsVisitor != null ? replaceGenericsVisitor.VisitDynamic(property.PropertyType) : property.PropertyType).FixupValueType();

                    var updatablePropertyInflatedCtor = GetOrCreateUpdatablePropertyCtor(context.Assembly, propertyType);

                    il.Emit(OpCodes.Newobj, updatablePropertyInflatedCtor);
                    il.Emit(OpCodes.Call, updateEngineRegisterMemberMethod);
                }
            }

            if (updateCurrentMethod != updateMainMethod)
            {
                // If we have a local method, close it
                il.Emit(OpCodes.Ret);

                // Also call it from main method if it was a closed generic instantiation
                if (type is GenericInstanceType)
                {
                    il = updateMainMethod.Body.GetILProcessor();
                    il.Emit(OpCodes.Call, updateCurrentMethod.MakeGeneric(((GenericInstanceType)type).GenericArguments.Select(context.Assembly.MainModule.ImportReference).Select(CecilExtensions.FixupValueType).ToArray()));
                }
            }
        }
예제 #9
0
        private static MethodDefinition InflateMethod(TypeDefinition inflatedType, MethodDefinition method, ResolveGenericsVisitor resolveGenericsVisitor)
        {
            var clonedMethod = new MethodDefinition(method.Name, method.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(method.ReturnType)));

            clonedMethod.Parameters.AddRange(
                method.Parameters.Select(x => new ParameterDefinition(x.Name, x.Attributes, inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.ParameterType)))));

            if (method.Body != null)
            {
                clonedMethod.Body.Variables.AddRange(
                    method.Body.Variables.Select(x => new VariableDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x.VariableType)))));


                clonedMethod.Body.InitLocals = method.Body.InitLocals;

                var mappedInstructions = new Dictionary <Instruction, Instruction>();
                foreach (var instruction in method.Body.Instructions)
                {
                    // Create nop instructions to start with (if we use actual opcode, it would do an operand check)
                    var mappedInstruction = Instruction.Create(OpCodes.Nop);
                    mappedInstruction.OpCode        = instruction.OpCode;
                    mappedInstruction.Operand       = instruction.Operand;
                    mappedInstructions[instruction] = mappedInstruction;
                }

                foreach (var instruction in method.Body.Instructions)
                {
                    // Fix operand
                    var mappedInstruction = mappedInstructions[instruction];
                    if (mappedInstruction.Operand is Instruction)
                    {
                        mappedInstruction.Operand = mappedInstructions[(Instruction)instruction.Operand];
                    }
                    else if (mappedInstruction.Operand is ParameterDefinition)
                    {
                        var parameterIndex = method.Parameters.IndexOf((ParameterDefinition)instruction.Operand);
                        mappedInstruction.Operand = clonedMethod.Parameters[parameterIndex];
                    }
                    else if (mappedInstruction.Operand is VariableDefinition)
                    {
                        var variableIndex = method.Body.Variables.IndexOf((VariableDefinition)instruction.Operand);
                        mappedInstruction.Operand = clonedMethod.Body.Variables[variableIndex];
                    }
                    else if (mappedInstruction.Operand is TypeReference)
                    {
                        var newTypeReference = resolveGenericsVisitor.VisitDynamic((TypeReference)mappedInstruction.Operand);
                        newTypeReference          = inflatedType.Module.ImportReference(newTypeReference);
                        mappedInstruction.Operand = newTypeReference;
                    }
                    else if (mappedInstruction.Operand is FieldReference)
                    {
                        var fieldReference    = (FieldReference)mappedInstruction.Operand;
                        var newFieldReference = new FieldReference(fieldReference.Name,
                                                                   inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.FieldType)),
                                                                   inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(fieldReference.DeclaringType)));
                        mappedInstruction.Operand = newFieldReference;
                    }
                    else if (mappedInstruction.Operand is MethodReference)
                    {
                        var methodReference = (MethodReference)mappedInstruction.Operand;

                        var genericInstanceMethod = methodReference as GenericInstanceMethod;
                        if (genericInstanceMethod != null)
                        {
                            methodReference = genericInstanceMethod.ElementMethod;
                        }

                        methodReference = methodReference.GetElementMethod();
                        var newMethodReference = new MethodReference(methodReference.Name,
                                                                     inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.ReturnType)),
                                                                     inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(methodReference.DeclaringType)))
                        {
                            HasThis           = methodReference.HasThis,
                            ExplicitThis      = methodReference.ExplicitThis,
                            CallingConvention = methodReference.CallingConvention,
                        };

                        foreach (var parameter in methodReference.Parameters)
                        {
                            newMethodReference.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType))));
                        }

                        if (methodReference.HasGenericParameters)
                        {
                            CopyGenericParameters(methodReference, newMethodReference);
                        }

                        if (genericInstanceMethod != null)
                        {
                            newMethodReference = newMethodReference.MakeGenericMethod(genericInstanceMethod.GenericArguments.Select(x => inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(x))).ToArray());
                        }

                        mappedInstruction.Operand = newMethodReference;
                    }
                    else if (mappedInstruction.Operand is Mono.Cecil.CallSite)
                    {
                        var callSite    = (Mono.Cecil.CallSite)mappedInstruction.Operand;
                        var newCallSite = new Mono.Cecil.CallSite(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(callSite.ReturnType)))
                        {
                            HasThis           = callSite.HasThis,
                            ExplicitThis      = callSite.ExplicitThis,
                            CallingConvention = callSite.CallingConvention,
                        };

                        foreach (var parameter in callSite.Parameters)
                        {
                            newCallSite.Parameters.Add(new ParameterDefinition(inflatedType.Module.ImportReference(resolveGenericsVisitor.VisitDynamic(parameter.ParameterType))));
                        }

                        mappedInstruction.Operand = newCallSite;
                    }
                    else if (mappedInstruction.Operand is Instruction[])
                    {
                        // Not used in UpdatableProperty<T>
                        throw new NotImplementedException();
                    }
                }

                clonedMethod.Body.Instructions.AddRange(method.Body.Instructions.Select(x => mappedInstructions[x]));
            }
            return(clonedMethod);
        }