Exemplo n.º 1
0
        private void WriteStructCopyMethodBody(TypeDefinition type, ManagedUnrealTypeInfo structInfo, MethodDefinition copyMethod)
        {
            VariableDefinition resultVar = new VariableDefinition(type);

            copyMethod.Body.Variables.Add(resultVar);

            ILProcessor processor = copyMethod.Body.GetILProcessor();

            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Ldobj, type);
            processor.Emit(OpCodes.Stloc, resultVar);

            Instruction lastBranchPosition = null;

            foreach (ManagedUnrealPropertyInfo propertyInfo in structInfo.Properties)
            {
                if (propertyInfo.IsCollection)
                {
                    FieldDefinition propField = null;

                    foreach (FieldDefinition field in type.Fields)
                    {
                        if (field.Name == propertyInfo.Name)
                        {
                            propField = field;
                            break;
                        }
                    }

                    if (propField == null)
                    {
                        continue;
                    }

                    Type collectionType = GetTypeFromTypeDefinition(propField.FieldType.Resolve());
                    collectionType = ManagedUnrealTypeInfo.MakeGenericTypeWithPropertyArgs(collectionType, propertyInfo);

                    System.Reflection.ConstructorInfo collectionCtor = null;
                    foreach (System.Reflection.ConstructorInfo ctor in collectionType.GetConstructors())
                    {
                        System.Reflection.ParameterInfo[] ctorParams = ctor.GetParameters();
                        if (ctorParams.Length == 1)
                        {
                            if (propertyInfo.Type.TypeCode == EPropertyType.Map)
                            {
                                if (ctorParams[0].ParameterType.Name.Contains("IDictionary") ||
                                    ctorParams[0].ParameterType.Name.Contains("IReadOnlyDictionary"))
                                {
                                    collectionCtor = ctor;
                                }
                            }
                            else if (ctorParams[0].ParameterType.Name.Contains("IEnumerable"))
                            {
                                collectionCtor = ctor;
                            }
                        }
                    }

                    if (collectionCtor == null)
                    {
                        continue;
                    }

                    processor.Emit(OpCodes.Ldarg_0);
                    if (lastBranchPosition != null)
                    {
                        // Branch to be inserted with a branch target of the just written instruction
                        processor.InsertAfter(lastBranchPosition, processor.Create(OpCodes.Brfalse, processor.Body.Instructions[processor.Body.Instructions.Count - 1]));
                        lastBranchPosition = null;
                    }
                    processor.Emit(OpCodes.Ldfld, propField);

                    lastBranchPosition = processor.Body.Instructions[processor.Body.Instructions.Count - 1];

                    processor.Emit(OpCodes.Ldloca, resultVar);
                    processor.Emit(OpCodes.Ldarg_0);
                    processor.Emit(OpCodes.Ldfld, propField);
                    processor.Emit(OpCodes.Newobj, assembly.MainModule.ImportEx(collectionCtor));
                    processor.Emit(OpCodes.Stfld, propField);
                }
            }

            processor.Emit(OpCodes.Ldloc, resultVar);
            if (lastBranchPosition != null)
            {
                // Branch to be inserted with a branch target of the just written instruction
                processor.InsertAfter(lastBranchPosition, processor.Create(OpCodes.Brfalse, processor.Body.Instructions[processor.Body.Instructions.Count - 1]));
                lastBranchPosition = null;
            }
            processor.Emit(OpCodes.Ret);

            FinalizeMethod(copyMethod);
        }