Esempio n. 1
0
        static TypeDefinition GeneratePropertyBag(Context context, TypeReference containerType, MethodReference createValueMethod, MethodReference createArrayMethod, MethodReference createListMethod, TypeReference unityObjectReference, TypeReference unityObjectListReference)
        {
            var propertyBagType = PropertyBag.GeneratePropertyBagHeader(context, containerType, out var ctorMethod, out var addPropertyMethod);
            var ctorMethodBody  = ctorMethod.Body;
            var il           = ctorMethodBody.GetILProcessor();
            var baseCtorCall = ctorMethodBody.Instructions.Last();

            foreach (var(member, nameOverride) in CodeGenUtils.GetPropertyMembers(containerType.Resolve()))
            {
                if (CodeGenUtils.TryGenerateUnityObjectProperty(context, containerType, null, member, il, addPropertyMethod, createValueMethod, createArrayMethod, createListMethod, unityObjectReference, unityObjectListReference))
                {
                    continue;
                }

                var memberType = context.ImportReference(Utility.GetMemberType(member).ResolveGenericParameter(containerType));

                if (memberType.IsGenericInstance || memberType.IsArray)
                {
                    PropertyBag.RegisterCollectionTypes(context, containerType, memberType, il);
                }

                TypeDefinition propertyType;

                // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                if (member.IsPublic())
                {
                    propertyType = Property.Generate(context, containerType, member, nameOverride);
                }
                else
                {
#if !NET_DOTS
                    propertyType = ReflectedProperty.Generate(context, containerType, member, nameOverride);
#else
                    throw new Exception("Private properties require reflection which is not supported in NET_DOTS.");
#endif
                }

                propertyBagType.NestedTypes.Add(propertyType);

                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Newobj, propertyType.GetConstructors().First());
                il.Emit(OpCodes.Call, context.Module.ImportReference(addPropertyMethod.MakeGenericInstanceMethod(memberType)));
            }

            il.Emit(OpCodes.Ret);

            var nop   = il.Create(OpCodes.Nop);
            var ret   = il.Create(OpCodes.Ret);
            var leave = il.Create(OpCodes.Leave, ret);

            il.InsertAfter(ctorMethodBody.Instructions.Last(), nop);
            il.InsertAfter(nop, leave);
            il.InsertAfter(leave, ret);

            var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                TryStart     = baseCtorCall.Next,
                TryEnd       = nop,
                HandlerStart = nop,
                HandlerEnd   = ret,
                CatchType    = context.Module.ImportReference(typeof(Exception))
            };

            ctorMethodBody.ExceptionHandlers.Add(handler);

            return(propertyBagType);
        }
        static TypeDefinition GeneratePropertyBag(Context context, TypeReference containerType, TypeDefinition externalContainer,
                                                  Dictionary <string, TypeDefinition> externalContainerTypes, MethodReference getTypeMethod,
                                                  MethodReference createValueMethod, MethodReference createArrayMethod, MethodReference createListMethod,
                                                  TypeReference unityObjectReference, TypeReference unityObjectListReference, TypeReference listType)
        {
            var effectiveContainerType = externalContainer ?? containerType;
            var propertyBagType        = PropertyBag.GeneratePropertyBagHeader(context, effectiveContainerType, out var ctorMethod, out var addPropertyMethod);
            var il = ctorMethod.Body.GetILProcessor();

            foreach (var(member, nameOverride) in CodeGenUtils.GetPropertyMembers(containerType.Resolve()))
            {
                if (CodeGenUtils.TryGenerateUnityObjectProperty(context, containerType, externalContainer, member, il, addPropertyMethod, createValueMethod, createArrayMethod, createListMethod, unityObjectReference, unityObjectListReference))
                {
                    continue;
                }

                var           memberType = context.ImportReference(Utility.GetMemberType(member).ResolveGenericParameter(containerType));
                TypeReference externalMember;
                if (memberType.IsArray)
                {
                    externalContainerTypes.TryGetValue(memberType.GetElementType().FullName, out var externalMemberDefinition);
                    externalMember = externalMemberDefinition?.MakeArrayType();
                }
                else if (CodeGenUtils.IsListType(memberType, out var genericInstance))
                {
                    externalContainerTypes.TryGetValue(genericInstance.GenericArguments[0].FullName, out var externalMemberDefinition);
                    externalMember = externalMemberDefinition == null ? null : listType.MakeGenericInstanceType(externalMemberDefinition);
                }
                else
                {
                    externalContainerTypes.TryGetValue(memberType.FullName, out var externalMemberDefinition);
                    externalMember = externalMemberDefinition;
                }

                var effectiveMemberType = externalMember ?? memberType;
                if (memberType.IsGenericInstance || memberType.IsArray)
                {
                    PropertyBag.RegisterCollectionTypes(context, effectiveContainerType, effectiveMemberType, il);
                }

                TypeDefinition propertyType;
                if (externalMember != null || externalContainer != null)
                {
                    propertyType = ReflectedExternalProperty.Generate(context, containerType, externalContainer, member, externalMember, getTypeMethod, nameOverride);
                }
                else if (member.IsPublicOrAssembly())
                {
                    propertyType = Property.Generate(context, containerType, member, nameOverride);
                }
                else
                {
#if !NET_DOTS
                    propertyType = ReflectedProperty.Generate(context, containerType, member, nameOverride);
#else
                    throw new Exception("Private properties require reflection which is not supported in NET_DOTS.");
#endif
                }

                propertyBagType.NestedTypes.Add(propertyType);

                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Newobj, propertyType.GetConstructors().First());
                il.Emit(OpCodes.Call, context.Module.ImportReference(addPropertyMethod.MakeGenericInstanceMethod(effectiveMemberType)));
            }

            il.Emit(OpCodes.Ret);
            return(propertyBagType);
        }