/// <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();
        }
        /// <summary>
        /// Overrides the target <paramref name="method"/> with a method that throws a <see cref="NotImplementedException"/>.
        /// </summary>
        /// <param name="type">The target type.</param>
        /// <param name="module">The host module.</param>
        /// <param name="overrider">The <see cref="MethodOverrider"/> that will be used to override the target method.</param>
        /// <param name="method">The target method.</param>
        /// <returns>The stubbed method.</returns>
        private static MethodDefinition CreateMethodStub(TypeDefinition type, ModuleDefinition module, MethodOverrider overrider, MethodInfo method)
        {
            // Import the NotImplementedException type
            var notImplementedCtor = module.ImportConstructor<NotImplementedException>();
            var currentMethod = overrider.AddOverrideFor(method, type);

            // Create the method stub
            var body = currentMethod.Body;
            var il = body.GetILProcessor();

            il.Emit(OpCodes.Newobj, notImplementedCtor);
            il.Emit(OpCodes.Throw);

            return currentMethod;
        }
        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");
        }
        public void ImportReferences(ModuleDefinition module)
        {
            // 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
            _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);
        }
        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 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);
        }
Example #7
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");
        }
Example #8
0
        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");
        }
Example #9
0
        /// <summary>
        /// Modifies the default constructor to initialize the "__initializedServices" field so that it can ensure that all
        /// services called with the <see cref="IInitialize.Initialize"/> are initialized once per object lifetime.
        /// </summary>
        /// <param name="containerType">The container type.</param>
        /// <param name="module">The module.</param>
        /// <param name="fieldEmitter">The field builder.</param>
        private void AddInitializationMap(TypeDefinition containerType, ModuleDefinition module, FieldBuilder fieldEmitter)
        {
            var initializationMapType = module.Import(typeof(Dictionary<int, int>));
            var initializationMapField = new FieldDefinition("__initializedServices",
                                                             FieldAttributes.Private | FieldAttributes.InitOnly,
                                                             initializationMapType);
            containerType.Fields.Add(initializationMapField);

            var defaultConstructor = containerType.GetDefaultConstructor();
            var body = defaultConstructor.Body;

            // __initializedServices = new Dictionary<int, int>();
            var il = body.GetILProcessor();
            var dictionaryCtor = module.ImportConstructor<Dictionary<int, int>>();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, dictionaryCtor);
            il.Emit(OpCodes.Stfld, initializationMapField);
        }
Example #10
0
        /// <summary>
        /// Modifies the default constructor of a container type so that the jump labels used in the <see cref="IMicroContainer.GetInstance"/> implementation
        /// will be precalculated every time the compiled container is instantiated.
        /// </summary>
        /// <param name="module">The target module.</param>
        /// <param name="jumpTargetField">The field that holds the jump entries.</param>
        /// <param name="targetType">The container type.</param>
        /// <param name="getServiceHash">The hash calculation method.</param>
        /// <param name="serviceMap">The collection that contains the current list of dependencies and their respective implementations.</param>
        /// <param name="jumpTargets">A dictionary that maps dependencies to their respective label indexes.</param>
        private static void AddJumpEntries(ModuleDefinition module, FieldDefinition jumpTargetField, TypeDefinition targetType, MethodReference getServiceHash, IDictionary<IDependency, IImplementation> serviceMap, IDictionary<IDependency, int> jumpTargets)
        {
            var defaultContainerConstructor = targetType.GetDefaultConstructor();

            var body = defaultContainerConstructor.Body;
            var il = body.GetILProcessor();

            // Remove the last instruction and replace it with the jump entry
            // initialization instructions
            RemoveLastInstruction(body);

            // Initialize the jump targets in the default container constructor
            var getTypeFromHandleMethod = typeof(System.Type).GetMethod("GetTypeFromHandle", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
            var getTypeFromHandle = module.Import(getTypeFromHandleMethod);

            // __jumpTargets = new Dictionary<int, int>();
            var dictionaryCtor = module.ImportConstructor<Dictionary<int, int>>();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, dictionaryCtor);
            il.Emit(OpCodes.Stfld, jumpTargetField);

            var addMethod = module.ImportMethod<Dictionary<int, int>>("Add");
            var index = 0;
            foreach (var dependency in serviceMap.Keys)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, jumpTargetField);

                var serviceType = dependency.ServiceType;
                var serviceTypeRef = module.Import(serviceType);

                // Push the service type
                il.Emit(OpCodes.Ldtoken, serviceTypeRef);
                il.Emit(OpCodes.Call, getTypeFromHandle);

                // Push the service name
                var pushName = dependency.ServiceName == null ? il.Create(OpCodes.Ldnull) : il.Create(OpCodes.Ldstr, dependency.ServiceName);
                il.Append(pushName);

                // Calculate the hash code using the service type and service name
                il.Emit(OpCodes.Call, getServiceHash);

                // Map the current dependency to the index
                // that will be used in the GetInstance switch statement
                jumpTargets[dependency] = index;

                il.Emit(OpCodes.Ldc_I4, index++);
                il.Emit(OpCodes.Callvirt, addMethod);
            }
        }