public static TypeDefinition Generate(Context context, TypeReference containerType)
        {
            var propertyBagType = GeneratePropertyBagHeader(context, containerType, out var ctorMethod, out var addPropertyMethod);
            var il = ctorMethod.Body.GetILProcessor();

            foreach (var member in Utility.GetPropertyMembers(context, containerType.Resolve()))
            {
                var memberType = context.ImportReference(Utility.GetMemberType(member).ResolveGenericParameter(containerType));

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

                TypeDefinition propertyType;

                if (member.IsPublic())
                {
                    propertyType = Property.Generate(context, containerType, member);
                }
                else
                {
#if !NET_DOTS
                    propertyType = ReflectedProperty.Generate(context, containerType, member);
#else
                    continue;
#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);
            return(propertyBagType);
        }
예제 #2
0
        public static TypeDefinition Generate(Context context, TypeReference containerType)
        {
            var basePropertyBagType = context.ImportReference(typeof(ContainerPropertyBag <>)).MakeGenericInstanceType(containerType);

            var propertyBagType = new TypeDefinition
                                  (
                @namespace: Context.kNamespace,
                @name: Utility.GetSanitizedName(containerType.FullName, "_PropertyBag"),
                @attributes: TypeAttributes.Class | TypeAttributes.NotPublic,
                @baseType: basePropertyBagType
                                  )
            {
                Scope = containerType.Scope
            };

            // NOTE: We create our own method reference since this assembly may not reference Unity.Properties on it's own. Thus any attempt
            // to Resolve() a TypeReference from Properties will return null. So instead we create MethodReferences for methods we
            // know will exist ourselves and let the new assembly, which will now include a reference to Properties, resolve at runtime
            var baseCtorMethod = new MethodReference(".ctor", context.ImportReference(typeof(void)), basePropertyBagType)
            {
                HasThis           = true,
                ExplicitThis      = false,
                CallingConvention = MethodCallingConvention.Default
            };

            var ctorMethod = new MethodDefinition
                             (
                ".ctor",
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                context.ImportReference(typeof(void))
                             );

            propertyBagType.Methods.Add(ctorMethod);

            var il = ctorMethod.Body.GetILProcessor();

            il.Emit(OpCodes.Ldarg_0); // this
            il.Emit(OpCodes.Call, context.Module.ImportReference(baseCtorMethod));

            var addPropertyMethod = context.Module.ImportReference(context.ContainerPropertyBagAddPropertyGenericMethodReference.Value.MakeGenericHostMethod(basePropertyBagType));

            foreach (var member in Utility.GetPropertyMembers(context, containerType.Resolve()))
            {
                var memberType = context.ImportReference(Utility.GetMemberType(member).ResolveGenericParameter(containerType));

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

                TypeDefinition propertyType;

                if (!member.IsPrivate())
                {
                    propertyType = Property.Generate(context, containerType, member);
                }
                else
                {
#if !NET_DOTS
                    propertyType = ReflectedProperty.Generate(context, containerType, member);
#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);
            return(propertyBagType);
        }