Ejemplo n.º 1
0
        void GenerateInnerInjectorType(TypeDefinition typeDef, InjectTypeInfo injectTypeInfo)
        {
            var injectorTypeDef = new TypeDefinition(
                "",
                "__GeneratedInjector",
                TypeAttributes.NestedPrivate | TypeAttributes.Sealed,
                module.TypeSystem.Object);

            var injectorImpl = new InterfaceImplementation(InjectorTypeRef);

            injectorTypeDef.Interfaces.Add(injectorImpl);

            GenerateDefaultConstructor(injectorTypeDef);
            GenerateInjectMethod(typeDef, injectorTypeDef, injectTypeInfo);
            GenerateCreateInstanceMethod(typeDef, injectorTypeDef, injectTypeInfo);
            GenerateInjectorGetterMethod(typeDef, injectorTypeDef);

            typeDef.NestedTypes.Add(injectorTypeDef);
        }
Ejemplo n.º 2
0
        void GenerateInjectMethod(TypeDefinition typeDef, TypeDefinition injectorTypeDef, InjectTypeInfo injectTypeInfo)
        {
            var methodDef = new MethodDefinition("Inject",
                                                 MethodAttributes.Public | MethodAttributes.Virtual,
                                                 module.TypeSystem.Void);

            injectorTypeDef.Methods.Add(methodDef);

            methodDef.Parameters.Add(new ParameterDefinition(module.TypeSystem.Object)
            {
                Name = "instance"
            });

            methodDef.Parameters.Add(new ParameterDefinition(ObjectResolverTypeRef)
            {
                Name = "resolver"
            });

            methodDef.Parameters.Add(new ParameterDefinition(InjectParameterListTypeRef)
            {
                Name = "parameters"
            });

            var body      = methodDef.Body;
            var processor = body.GetILProcessor();

            processor.Emit(OpCodes.Nop);

            var instanceVariableDef = new VariableDefinition(typeDef);

            body.Variables.Add(instanceVariableDef);

            if (injectTypeInfo.InjectMethods != null ||
                injectTypeInfo.InjectFields != null ||
                injectTypeInfo.InjectProperties != null)
            {
                processor.Emit(OpCodes.Ldarg_1);
                processor.Emit(OpCodes.Unbox_Any, typeDef);
                processor.Emit(OpCodes.Stloc_S, instanceVariableDef);
            }

            if (injectTypeInfo.InjectFields != null)
            {
                foreach (var injectField in injectTypeInfo.InjectFields)
                {
                    var fieldRef     = module.ImportReference(injectField);
                    var fieldTypeRef = Utils.CreateParameterTypeReference(module, injectField.FieldType, typeDef);

                    processor.Emit(OpCodes.Ldloc_S, instanceVariableDef);

                    // TODO: Add ExceptionHandler
                    // instance.Field = resolver.Resolve(Type)
                    processor.Emit(OpCodes.Ldarg_2);
                    processor.Emit(OpCodes.Ldtoken, fieldTypeRef);
                    processor.Emit(OpCodes.Call, GetTypeFromHandleRef);
                    processor.Emit(OpCodes.Call, ResolveMethodRef);
                    processor.Emit(OpCodes.Stfld, fieldRef);
                }
            }

            if (injectTypeInfo.InjectProperties != null)
            {
                foreach (var injectProperty in injectTypeInfo.InjectProperties)
                {
                    var propertySetterRef = module.ImportReference(injectProperty.SetMethod);
                    var propertyTypeRef   = Utils.CreateParameterTypeReference(module, injectProperty.PropertyType, typeDef);

                    processor.Emit(OpCodes.Ldloc_S, instanceVariableDef);

                    // TODO: Add ExceptionHandler
                    // instance.Property = resolver.Resolve(Type)
                    processor.Emit(OpCodes.Ldarg_2);
                    processor.Emit(OpCodes.Ldtoken, propertyTypeRef);
                    processor.Emit(OpCodes.Call, GetTypeFromHandleRef);
                    processor.Emit(OpCodes.Call, ResolveMethodRef);
                    processor.Emit(OpCodes.Callvirt, propertySetterRef);
                }
            }

            if (injectTypeInfo.InjectMethods != null)
            {
                foreach (var injectMethod in injectTypeInfo.InjectMethods)
                {
                    var injectMethodRef = module.ImportReference(injectMethod.MethodInfo);
                    processor.Emit(OpCodes.Ldloc_S, instanceVariableDef);
                    for (var i = 0; i < injectMethodRef.Parameters.Count; i++)
                    {
                        var paramDef     = injectMethodRef.Parameters[i];
                        var paramInfo    = injectMethod.ParameterInfos[i];
                        var paramTypeRef = Utils.CreateParameterTypeReference(module, paramInfo.ParameterType, typeDef);

                        var paramVariableDef = new VariableDefinition(paramDef.ParameterType);
                        body.Variables.Add(paramVariableDef);

                        // TODO: Add ExceptionHandler
                        processor.Emit(OpCodes.Ldarg_2);
                        processor.Emit(OpCodes.Ldtoken, paramTypeRef);
                        processor.Emit(OpCodes.Call, GetTypeFromHandleRef);
                        processor.Emit(OpCodes.Ldstr, paramInfo.Name);
                        processor.Emit(OpCodes.Ldarg_3);
                        processor.Emit(OpCodes.Call, ResolveOrParameterMethodRef);
                        processor.Emit(OpCodes.Unbox_Any, paramTypeRef);
                        processor.Emit(OpCodes.Stloc_S, paramVariableDef);
                        processor.Emit(OpCodes.Ldloc_S, paramVariableDef);
                    }
                    processor.Emit(OpCodes.Callvirt, injectMethodRef);
                }
            }

            processor.Emit(OpCodes.Ret);
        }
Ejemplo n.º 3
0
        void GenerateCreateInstanceMethod(
            TypeDefinition typeDef,
            TypeDefinition injectorTypeDef,
            InjectTypeInfo injectTypeInfo)
        {
            var methodDef = new MethodDefinition("CreateInstance",
                                                 MethodAttributes.Public | MethodAttributes.Virtual,
                                                 module.TypeSystem.Object);

            var injectMethodDef = injectorTypeDef.Methods.Single(x => x.Name == "Inject");

            injectorTypeDef.Methods.Add(methodDef);

            methodDef.Parameters.Add(new ParameterDefinition(ObjectResolverTypeRef)
            {
                Name = "resolver"
            });

            methodDef.Parameters.Add(new ParameterDefinition(InjectParameterListTypeRef)
            {
                Name = "parameters"
            });

            var body      = methodDef.Body;
            var processor = body.GetILProcessor();

            processor.Emit(OpCodes.Nop);

            if (injectTypeInfo.InjectConstructor == null ||
                injectTypeInfo.Type.IsSubclassOf(typeof(UnityEngine.Component)))
            {
                processor.Emit(OpCodes.Ldnull);
                processor.Emit(OpCodes.Ret);
                return;
            }

            var resultVariableDef = new VariableDefinition(module.TypeSystem.Object);

            body.Variables.Add(resultVariableDef);

            var constructorRef = module.ImportReference(injectTypeInfo.InjectConstructor.ConstructorInfo);

            for (var i = 0; i < constructorRef.Parameters.Count; i++)
            {
                var paramDef     = constructorRef.Parameters[i];
                var paramInfo    = injectTypeInfo.InjectConstructor.ParameterInfos[i];
                var paramTypeRef = Utils.CreateParameterTypeReference(module, paramInfo.ParameterType, typeDef);

                var paramVariableDef = new VariableDefinition(paramTypeRef);
                body.Variables.Add(paramVariableDef);

                // TODO: Add ExceptionHandler
                // Call ResolveOrParameter(IObjectResolver, Type, string, IReadOnlyList<IInjectParameter>)
                processor.Emit(OpCodes.Ldarg_1);
                processor.Emit(OpCodes.Ldtoken, paramTypeRef);
                processor.Emit(OpCodes.Call, GetTypeFromHandleRef);
                processor.Emit(OpCodes.Ldstr, paramInfo.Name);
                processor.Emit(OpCodes.Ldarg_2);
                processor.Emit(OpCodes.Call, ResolveOrParameterMethodRef);
                processor.Emit(OpCodes.Unbox_Any, paramTypeRef);
                processor.Emit(OpCodes.Stloc_S, paramVariableDef);
                processor.Emit(OpCodes.Ldloc_S, paramVariableDef);
            }

            processor.Emit(OpCodes.Newobj, constructorRef);
            processor.Emit(OpCodes.Stloc_0);

            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Ldloc_0);
            processor.Emit(OpCodes.Ldarg_1);
            processor.Emit(OpCodes.Ldarg_2);
            processor.Emit(OpCodes.Callvirt, injectMethodDef);

            processor.Emit(OpCodes.Ldloc_0);
            processor.Emit(OpCodes.Ret);
        }