/// <summary>
        /// Generates a proxy that forwards all virtual method calls
        /// to a single <see cref="IInterceptor"/> instance.
        /// </summary>
        /// <param name="originalBaseType">The base class of the type being constructed.</param>
        /// <param name="baseInterfaces">The list of interfaces that the new type must implement.</param>
        /// <param name="module">The module that will hold the brand new type.</param>
        /// <param name="targetType">The <see cref="TypeDefinition"/> that represents the type to be created.</param>
        public override void Construct(Type originalBaseType, IEnumerable<Type> baseInterfaces, ModuleDefinition module,
            TypeDefinition targetType)
        {
            var interfaces = new HashSet<Type>(baseInterfaces);

            if (!interfaces.Contains(typeof (ISerializable)))
                interfaces.Add(typeof (ISerializable));

            var serializableInterfaceType = module.ImportType<ISerializable>();
            if (!targetType.Interfaces.Contains(serializableInterfaceType))
                targetType.Interfaces.Add(serializableInterfaceType);

            // Create the proxy type
            base.Construct(originalBaseType, interfaces, module, targetType);

            // Add the Serializable attribute
            targetType.IsSerializable = true;

            var serializableCtor = module.ImportConstructor<SerializableAttribute>();
            var serializableAttribute = new CustomAttribute(serializableCtor);
            targetType.CustomAttributes.Add(serializableAttribute);

            ImplementGetObjectData(originalBaseType, baseInterfaces, module, targetType);
            DefineSerializationConstructor(module, targetType);

            var interceptorType = module.ImportType<IInterceptor>();
            var interceptorGetterProperty = (from PropertyDefinition m in targetType.Properties
                where
                    m.Name == "Interceptor" &&
                    m.PropertyType == interceptorType
                select m).First();
        }
        public override void ImportReferences(ModuleDefinition module)
        {
            // Import the references from the base class
            base.ImportReferences(module);

            _modifiableInterfaceType = module.ImportType<IModifiableType>();
        }
        /// <summary>
        /// Emits the instructions that call <see cref="IInitialize.Initialize"/> on a given service instance.
        /// </summary>
        /// <param name="il"></param>
        /// <param name="module">The host module.</param>
        /// <param name="serviceInstance">The local variable that points to the current service instance.</param>
        public void Initialize(ILProcessor il, ModuleDefinition module, VariableDefinition serviceInstance)
        {
            var body = il.Body;
            var method = body.Method;
            var declaringType = method.DeclaringType;

            var targetField = GetTargetField(declaringType);
            if (targetField == null)
                return;

            var initializeType = module.ImportType<IInitialize>();

            il.Emit(OpCodes.Ldloc, serviceInstance);
            il.Emit(OpCodes.Isinst, initializeType);

            var initializeMethod = module.ImportMethod<IInitialize>("Initialize");
            var skipInitializationCall = il.Create(OpCodes.Nop);
            il.Emit(OpCodes.Brfalse, skipInitializationCall);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, targetField);
            GetServiceHash(il, module, serviceInstance);

            var containsMethod = module.ImportMethod<Dictionary<int, int>>("ContainsKey");
            il.Emit(OpCodes.Callvirt, containsMethod);
            il.Emit(OpCodes.Brtrue, skipInitializationCall);

            // if (!__initializedServices.ContainsKey(currentService.GetHashCode()) {
            il.Emit(OpCodes.Ldloc, serviceInstance);
            il.Emit(OpCodes.Isinst, initializeType);
            il.Emit(OpCodes.Ldarg_0);

            il.Emit(OpCodes.Callvirt, initializeMethod);

            // __initializedServices.Add(hashCode, 0);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, targetField);
            GetServiceHash(il, module, serviceInstance);
            il.Emit(OpCodes.Ldc_I4_1);

            var addMethod = module.ImportMethod<Dictionary<int, int>>("Add");
            il.Emit(OpCodes.Callvirt, addMethod);

            il.Append(skipInitializationCall);
        }
        private static void DefineSerializationConstructor(ModuleDefinition module, TypeDefinition targetType)
        {
            var getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle",
                BindingFlags.Public | BindingFlags.Static);

            var parameterTypes = new[] {typeof (SerializationInfo), typeof (StreamingContext)};

            // Define the constructor signature
            var serializationCtor = targetType.AddDefaultConstructor();
            serializationCtor.AddParameters(parameterTypes);

            serializationCtor.Attributes = MethodAttributes.HideBySig | MethodAttributes.SpecialName |
                                           MethodAttributes.RTSpecialName | MethodAttributes.Public;
            var interceptorInterfaceType = module.ImportType<IInterceptor>();
            var interceptorTypeVariable = serializationCtor.AddLocal<Type>();

            var body = serializationCtor.Body;
            body.InitLocals = true;

            var IL = serializationCtor.GetILGenerator();

            IL.Emit(OpCodes.Ldtoken, interceptorInterfaceType);
            IL.Emit(OpCodes.Call, getTypeFromHandle);
            IL.Emit(OpCodes.Stloc, interceptorTypeVariable);

            var defaultConstructor = module.ImportConstructor<object>();
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Call, defaultConstructor);

            // __interceptor = (IInterceptor)info.GetValue("__interceptor", typeof(IInterceptor));
            var getValue = module.ImportMethod<SerializationInfo>("GetValue");
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldstr, "__interceptor");
            IL.Emit(OpCodes.Ldloc, interceptorTypeVariable);
            IL.Emit(OpCodes.Callvirt, getValue);
            IL.Emit(OpCodes.Castclass, interceptorInterfaceType);

            var setInterceptor = module.ImportMethod<IProxy>("set_Interceptor");
            IL.Emit(OpCodes.Callvirt, setInterceptor);
            ;
            IL.Emit(OpCodes.Ret);
        }
        public void DefineGetAllInstancesMethod(TypeDefinition containerType, ModuleDefinition module, 
            IDictionary<IDependency, IImplementation> serviceMap)
        {
            var targetMethods = new List<MethodDefinition>();
            foreach (MethodDefinition method in containerType.Methods)
            {
                if (method.Name != "GetAllInstances")
                    continue;

                targetMethods.Add(method);
            }

            var getAllInstancesMethod = targetMethods[0];

            // Remove the stub implementation
            var body = getAllInstancesMethod.Body;
            var IL = body.GetILProcessor();

            body.InitLocals = true;
            body.Instructions.Clear();

            var listVariable = getAllInstancesMethod.AddLocal<List<object>>();
            var listCtor = module.ImportConstructor<List<object>>();
            IL.Emit(OpCodes.Newobj, listCtor);
            IL.Emit(OpCodes.Stloc, listVariable);

            // Group the dependencies by type
            var dependenciesByType = new HashList<System.Type, IDependency>();
            foreach (var dependency in serviceMap.Keys)
            {
                var serviceType = dependency.ServiceType;
                dependenciesByType.Add(serviceType, dependency);
            }

            var getTypeFromHandleMethod = typeof(System.Type).GetMethod("GetTypeFromHandle", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
            var getTypeFromHandle = module.Import(getTypeFromHandleMethod);
            var addItem = module.ImportMethod<List<object>>("Add");

            var currentService = getAllInstancesMethod.AddLocal<object>();

            foreach (var currentType in dependenciesByType.Keys)
            {
                var currentTypeRef = module.Import(currentType);

                var currentList = dependenciesByType[currentType];
                if (currentList.Count == 0)
                    continue;

                var skipAdd = IL.Create(OpCodes.Nop);
                IL.Emit(OpCodes.Ldarg_1);
                IL.Emit(OpCodes.Ldtoken, currentTypeRef);
                IL.Emit(OpCodes.Call, getTypeFromHandle);
                IL.Emit(OpCodes.Ceq);
                IL.Emit(OpCodes.Brfalse, skipAdd);

                foreach (var dependency in currentList)
                {
                    IL.Emit(OpCodes.Ldloc, listVariable);

                    var implementation = serviceMap[dependency];
                    implementation.Emit(dependency, serviceMap, getAllInstancesMethod);

                    IL.Emit(OpCodes.Stloc, currentService);

                    // Call IInitialize.Initialize(container) on the current service type
                    _initializer.Initialize(IL, module, currentService);

                    IL.Emit(OpCodes.Ldloc, currentService);
                    IL.Emit(OpCodes.Callvirt, addItem);
                }

                IL.Append(skipAdd);
            }

            var skipOtherContainerCall = IL.Create(OpCodes.Nop);

            var getNextContainer = module.ImportMethod<IMicroContainer>("get_NextContainer");
            var otherContainer = getAllInstancesMethod.AddLocal<IMicroContainer>();

            // var otherContainer = this.NextContainer;
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getNextContainer);
            IL.Emit(OpCodes.Stloc, otherContainer);

            // if (otherContainer != null && this != otherContainer) {
            IL.Emit(OpCodes.Ldloc, otherContainer);
            IL.Emit(OpCodes.Brfalse, skipOtherContainerCall);

            IL.Emit(OpCodes.Ldloc, otherContainer);
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Ceq);
            IL.Emit(OpCodes.Brtrue, skipOtherContainerCall);

            // var otherInstances = NextContainer.GetAllInstances(type);
            var otherGetAllInstancesMethod = module.ImportMethod<IMicroContainer>("GetAllInstances");

            IL.Emit(OpCodes.Ldloc, listVariable);
            IL.Emit(OpCodes.Ldloc, otherContainer);
            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Callvirt, otherGetAllInstancesMethod);

            // resultList.AddRange(otherInstances);
            var addRangeMethod = module.ImportMethod<List<object>>("AddRange");
            IL.Emit(OpCodes.Callvirt, addRangeMethod);

            // }

            // Cast the results down to an IEnumerable<object>
            var enumerableType = module.ImportType<IEnumerable<object>>();
            IL.Append(skipOtherContainerCall);
            IL.Emit(OpCodes.Ldloc, listVariable);
            IL.Emit(OpCodes.Isinst, enumerableType);
            IL.Emit(OpCodes.Ret);
        }
        private static void ImplementGetObjectData(Type originalBaseType, IEnumerable<Type> baseInterfaces,
            ModuleDefinition module, TypeDefinition targetType)
        {
            var getObjectDataMethod = (from MethodDefinition m in targetType.Methods
                where m.Name.Contains("ISerializable.GetObjectData")
                select m).First();

            var body = getObjectDataMethod.Body;
            body.Instructions.Clear();
            body.InitLocals = true;

            var IL = getObjectDataMethod.GetILGenerator();

            var proxyInterfaceType = module.ImportType<IProxy>();
            var getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle",
                BindingFlags.Public | BindingFlags.Static);
            var proxyObjectRefType = module.ImportType<ProxyObjectReference>();
            var setType = module.ImportMethod<SerializationInfo>("SetType",
                BindingFlags.Public | BindingFlags.Instance);
            var getInterceptor = module.ImportMethod<IProxy>("get_Interceptor");

            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldtoken, proxyObjectRefType);
            IL.Emit(OpCodes.Call, getTypeFromHandle);
            IL.Emit(OpCodes.Callvirt, setType);

            // info.AddValue("__interceptor", __interceptor);
            var addValueMethod = typeof (SerializationInfo).GetMethod("AddValue",
                BindingFlags.Public | BindingFlags.Instance,
                null,
                new[] {typeof (string), typeof (object)},
                null);
            var addValue = module.Import(addValueMethod);

            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldstr, "__interceptor");
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Castclass, proxyInterfaceType);
            IL.Emit(OpCodes.Callvirt, getInterceptor);
            IL.Emit(OpCodes.Callvirt, addValue);

            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldstr, "__baseType");
            IL.Emit(OpCodes.Ldstr, originalBaseType.AssemblyQualifiedName);
            IL.Emit(OpCodes.Callvirt, addValue);

            var baseInterfaceCount = baseInterfaces.Count();

            // Save the number of base interfaces
            var integerType = module.ImportType<Int32>();
            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Ldstr, "__baseInterfaceCount");
            IL.Emit(OpCodes.Ldc_I4, baseInterfaceCount);
            IL.Emit(OpCodes.Box, integerType);
            IL.Emit(OpCodes.Callvirt, addValue);

            var index = 0;
            foreach (var baseInterface in baseInterfaces)
            {
                IL.Emit(OpCodes.Ldarg_1);
                IL.Emit(OpCodes.Ldstr, string.Format("__baseInterface{0}", index++));
                IL.Emit(OpCodes.Ldstr, baseInterface.AssemblyQualifiedName);
                IL.Emit(OpCodes.Callvirt, addValue);
            }

            IL.Emit(OpCodes.Ret);
        }
        public override void ImportReferences(ModuleDefinition module)
        {
            var types = new[] { typeof(object),
                                 typeof(MethodBase),
                                 typeof(StackTrace),
                                 typeof(Type[]),
                                 typeof(Type[]),
                                 typeof(Type),
                                 typeof(object[]) };

            _invocationInfoCtor = module.ImportConstructor<InvocationInfo>(types);
            _stackCtor = module.ImportConstructor<Stack<object>>(new Type[0]);

            _pushMethod = module.ImportMethod<Stack<object>>("Push");
            _popMethod = module.ImportMethod<Stack<object>>("Pop");
            _toArray = module.ImportMethod<Stack<object>>("ToArray");
            _getProvider = module.ImportMethod<IMethodReplacementHost>("get_MethodCallReplacementProvider");
            _getStaticProvider = module.ImportMethod("GetProvider", typeof(MethodCallReplacementProviderRegistry));

            _canReplace = module.ImportMethod<IMethodReplacementProvider>("CanReplace");
            _getReplacement = module.ImportMethod<IMethodReplacementProvider>("GetMethodReplacement");
            _hostInterfaceType = module.ImportType<IMethodReplacementHost>();
            _intercept = module.ImportMethod<IInterceptor>("Intercept");
        }
        /// <summary>
        /// Defines the static constructor for the nested type.
        /// </summary>
        /// <param name="module">The target module.</param>
        /// <param name="nestedType">The nested type itself.</param>
        /// <returns>The nested static constructor itself.</returns>
        private static MethodDefinition DefineStaticConstructor(ModuleDefinition module, TypeDefinition nestedType)
        {
            // Define the nested static constructor
            var voidType = module.ImportType(typeof(void));
            var attributes = MethodAttributes.Private |
                             MethodAttributes.HideBySig |
                             MethodAttributes.Static |
                             MethodAttributes.RTSpecialName |
                             MethodAttributes.SpecialName;

            var cctor = new MethodDefinition(".cctor", attributes, voidType);

            cctor.ImplAttributes = Mono.Cecil.MethodImplAttributes.IL | Mono.Cecil.MethodImplAttributes.Managed;
            nestedType.Methods.Add(cctor);

            return cctor;
        }
 /// <summary>
 /// Imports references into the target module.
 /// </summary>
 /// <param name="module">The module containing the type to be modified.</param>
 public void ImportReferences(ModuleDefinition module)
 {
     _hostInterfaceType = module.ImportType<IFieldInterceptionHost>();
     _interceptorPropertyType = module.ImportType<IFieldInterceptor>();
 }
        public void ImportReferences(ModuleDefinition module)
        {
            // Type imports
            _hostInterfaceType = module.ImportType<IActivatorHost>();
            _methodActivatorType = module.ImportType<ITypeActivator>();
            _objectType = module.ImportType<object>();
            _voidType = module.Import(typeof(void));
            _objectListType = module.ImportType<List<object>>();

            // Static method imports
            _getStaticActivator = module.ImportMethod("GetActivator", typeof(TypeActivatorRegistry), BindingFlags.Public | BindingFlags.Static);
            _getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);

            // Constructor imports
            _methodActivationContextCtor = module.ImportConstructor<TypeActivationContext>(typeof(object), typeof(MethodBase), typeof(Type), typeof(object[]));

            // Instance method imports
            _getActivator = module.ImportMethod<IActivatorHost>("get_Activator");
            _objectListCtor = module.ImportConstructor<List<object>>(new Type[0]);
            _toArrayMethod = module.ImportMethod<List<object>>("ToArray", new Type[0]);
            _addMethod = module.ImportMethod<List<object>>("Add", new Type[] { typeof(object) });
            _reverseMethod = module.ImportMethod<List<object>>("Reverse", new Type[0]);
            _canActivate = module.ImportMethod<ITypeActivator>("CanActivate");
            _getItem = module.ImportMethod<List<object>>("get_Item", new Type[] { typeof(int) });

            var createInstanceMethod = typeof(IActivator<ITypeActivationContext>).GetMethod("CreateInstance");

            _createInstance = module.Import(createInstanceMethod);
        }
        /// <summary>
        /// Pushes the arguments of a method onto the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="method">The target method.</param>
        /// <param name="arguments">The <see cref="VariableDefinition">local variable</see> that will hold the array of arguments.</param>
        public static void PushArguments(this CilWorker IL, IMethodSignature method, ModuleDefinition module,
            VariableDefinition arguments)
        {
            var objectType = module.ImportType(typeof (object));
            var parameterCount = method.Parameters.Count;
            IL.Emit(OpCodes.Ldc_I4, parameterCount);
            IL.Emit(OpCodes.Newarr, objectType);
            IL.Emit(OpCodes.Stloc, arguments);

            if (parameterCount == 0)
                return;

            var index = 0;
            foreach (ParameterDefinition param in method.Parameters)
            {
                IL.PushParameter(index++, arguments, param);
            }
        }
        /// <summary>
        /// Converts the return value of a method into the <paramref name="returnType">target type</paramref>.
        /// If the target type is void, then the value will simply be popped from the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="returnType">The method return type itself.</param>
        public static void PackageReturnValue(this CilWorker IL, ModuleDefinition module, TypeReference returnType)
        {
            var voidType = module.ImportType(typeof (void));
            if (returnType == voidType)
            {
                IL.Emit(OpCodes.Pop);
                return;
            }

            IL.Emit(OpCodes.Unbox_Any, returnType);
        }
        /// <summary>
        /// Defines the nested type that will instantiate the actual singleton service instance.
        /// </summary>
        /// <param name="module">The module that will host the singleton type.</param>
        /// <param name="singletonType">The singleton type.</param>
        /// <param name="instanceField">The field that will hold the singleton instance.</param>
        /// <param name="serviceMap">The service map that contains the list of dependencies in the application.</param>
        /// <param name="implementation">The implementation that will instantiate the dependency.</param>
        /// <param name="dependency">The dependency that will be instantiated by the singleton.</param>
        /// <param name="targetMethod">The method that will be used to instantiate the actual service instance.</param>
        private void DefineNestedType(ModuleDefinition module, TypeDefinition singletonType, FieldDefinition instanceField, IDictionary<IDependency, IImplementation> serviceMap, IImplementation implementation, IDependency dependency, MethodDefinition targetMethod)
        {
            var objectType = module.ImportType(typeof (object));
            var nestedName = string.Format("Nested-{0}", dependency.GetHashCode());

            const TypeAttributes nestedAttributes = TypeAttributes.NestedFamORAssem | TypeAttributes.Sealed | TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.AnsiClass;
            var nestedType = module.DefineClass(nestedName, "Hiro.Containers.Internal", nestedAttributes, objectType);
            singletonType.NestedTypes.Add(nestedType);

            nestedType.Fields.Add(instanceField);

            // Emit the static constructor body
            var cctor = DefineNestedConstructors(module, nestedType);

            EmitSingletonInstantiation(dependency, implementation, serviceMap, instanceField, cctor, module, targetMethod);
        }
 public void AddAdditionalMembers(ModuleDefinition module)
 {
     _hostInterfaceType = module.ImportType<IActivatorHost>();
     _activatorPropertyType = module.ImportType<ITypeActivator>();
 }
Exemple #15
0
        /// <summary>
        /// Adds references to the target module.
        /// </summary>
        /// <param name="module">The module that will be modified.</param>
        public override void ImportReferences(ModuleDefinition module)
        {
            var parameterTypes = new[] {typeof (object), typeof (MethodBase), typeof (FieldInfo), typeof (Type)};

            _fieldInterceptionHostType = module.ImportType<IFieldInterceptionHost>();

            _fieldContextCtor = module.ImportConstructor<FieldInterceptionContext>(parameterTypes);
            module.ImportMethod<FieldInfo>("GetFieldFromHandle",
                new[] {typeof (RuntimeFieldHandle), typeof (RuntimeTypeHandle)});
            module.ImportMethod<object>("GetType");
            _getInterceptor = module.ImportMethod<FieldInterceptorRegistry>("GetInterceptor");
            _getInstanceInterceptor = module.ImportMethod<IFieldInterceptionHost>("get_FieldInterceptor");
            _canIntercept = module.ImportMethod<IFieldInterceptor>("CanIntercept");

            _getValue = module.ImportMethod<IFieldInterceptor>("GetValue");
            _setValue = module.ImportMethod<IFieldInterceptor>("SetValue");
        }
        public override void ImportReferences(ModuleDefinition module)
        {
            // Keep track of the module that contains the ITypeFilter type
            // so that the InterceptMethodCalls class will skip
            // trying to intercept types within the LinFu.Aop.Cecil assembly
            var typeFilterType = module.ImportType<ITypeFilter>();
            _linfuAopModule = typeFilterType.Module;

            var activatorHostType = module.ImportType<IActivatorHost>();
            _linfuAopInterfaceModule = activatorHostType.Module;

            var types = new[] { typeof(object),
                                 typeof(MethodBase),
                                 typeof(StackTrace),
                                 typeof(Type[]),
                                 typeof(Type[]),
                                 typeof(Type),
                                 typeof(object[]) };

            _invocationInfoCtor = module.ImportConstructor<InvocationInfo>(types);
            _stackCtor = module.ImportConstructor<Stack<object>>(new Type[0]);

            _pushMethod = module.ImportMethod<Stack<object>>("Push");
            _popMethod = module.ImportMethod<Stack<object>>("Pop");
            _toArray = module.ImportMethod<Stack<object>>("ToArray");
            _getProvider = module.ImportMethod<IMethodReplacementHost>("get_MethodCallReplacementProvider");
            _getStaticProvider = module.ImportMethod("GetProvider", typeof(MethodCallReplacementProviderRegistry));

            _canReplace = module.ImportMethod<IMethodReplacementProvider>("CanReplace");
            _getReplacement = module.ImportMethod<IMethodReplacementProvider>("GetMethodReplacement");
            _hostInterfaceType = module.ImportType<IMethodReplacementHost>();
            _intercept = module.ImportMethod<IInterceptor>("Intercept");
        }
Exemple #17
0
 private static bool ValidMethod(ModuleDefinition moduleDefinition, string excludeAttributeName, MethodDefinition x)
 {
     return !x.ContainsAttribute(excludeAttributeName)
            &&
            x.HasBody
            &&
            (
                (
                     !x.IsSpecialName
                     ||
                     x.IsConstructor
                )
                &&
                !x.IsGetter
                &&
                !x.IsSetter
                &&
                !x.ContainsAttribute(moduleDefinition.ImportType<CompilerGeneratedAttribute>())
            );
 }