public void Replace(IMethodContext context, ModuleDefinition targetModule) { var currentMethod = context.CurrentMethod; var currentArguments = context.CurrentArguments; var currentArgument = context.CurrentArgument; var pushMethod = targetModule.ImportMethod<Stack<object>>("Push"); var worker = context.CilWorker; var methodMap = _context.MethodMap; var targetDependency = _context.TargetDependency; var interfaceType = _context.InterfaceType; var adapterConstructor = _adapterBuilder.CreateAdapterConstructor(methodMap); foreach (ParameterReference param in currentMethod.Parameters) { var arguments = new ParameterContext(worker, interfaceType, pushMethod, currentArguments, currentArgument, targetDependency, adapterConstructor, param); // Save the current argument _pushParameter.Adapt(arguments); } }
/// <summary> /// Emits a call that obtains the hash code for the current service instance. /// </summary> /// <param name="il">The <see cref="ILProcessor"/> that points to the method body.</param> /// <param name="module">The target module.</param> /// <param name="serviceInstance">The local variable that contains the service instance.</param> private void GetServiceHash(ILProcessor il, ModuleDefinition module, VariableDefinition serviceInstance) { il.Emit(OpCodes.Ldloc, serviceInstance); var getHashCodeMethod = module.ImportMethod<object>("GetHashCode"); il.Emit(OpCodes.Callvirt, getHashCodeMethod); }
/// <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); }
/// <summary> /// Emits the instructions that will obtain the <see cref="IMicroContainer"/> instance. /// </summary> /// <param name="module">The target module.</param> /// <param name="microContainerType">The type reference that points to the <see cref="IMicroContainer"/> type.</param> /// <param name="worker">The <see cref="CilWorker"/> that points to the <see cref="IMicroContainer.GetInstance"/> method body.</param> /// <param name="skipCreate">The skip label that will be used if the service cannot be instantiated.</param> protected override void EmitGetContainerInstance(ModuleDefinition module, TypeReference microContainerType, ILProcessor il, Instruction skipCreate) { var getNextContainer = module.ImportMethod<IMicroContainer>("get_NextContainer"); EmitGetNextContainerCall(il, microContainerType, getNextContainer); il.Emit(OpCodes.Brfalse, skipCreate); // var result = NextContainer.GeService(serviceType, serviceName); EmitGetNextContainerCall(il, microContainerType, getNextContainer); }
public void Replace(IMethodContext context, ModuleDefinition targetModule) { var currentMethod = context.CurrentMethod; var currentArguments = context.CurrentArguments; var popMethod = targetModule.ImportMethod<Stack<object>>("Pop"); var IL = context.CilWorker; foreach (ParameterReference param in currentMethod.Parameters) { IL.Emit(OpCodes.Ldloc, currentArguments); IL.Emit(OpCodes.Callvirt, popMethod); IL.Emit(OpCodes.Unbox_Any, param.ParameterType); } }
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); }
private static void Emit(CilWorker IL, ModuleDefinition module, VariableDefinition surroundingImplementation, VariableDefinition invocationInfo, VariableDefinition returnValue) { Instruction skipInvoke = IL.Create(OpCodes.Nop); Instruction skipPrint = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Brtrue, skipPrint); IL.Append(skipPrint); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke); MethodReference aroundInvoke = module.ImportMethod<IAfterInvoke>("AfterInvoke"); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Ldloc, invocationInfo); IL.Emit(OpCodes.Ldloc, returnValue); IL.Emit(OpCodes.Callvirt, aroundInvoke); IL.Append(skipInvoke); }
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); }
/// <summary> /// Pushes the current <paramref name="field"/> onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="field">The field that represents the <see cref="FieldInfo"/> that will be pushed onto the stack.</param> /// <param name="module">The module that contains the target field.</param> public static void PushField(this CilWorker IL, FieldReference field, ModuleDefinition module) { var getFieldFromHandle = module.ImportMethod<FieldInfo>("GetFieldFromHandle", typeof (RuntimeFieldHandle), typeof (RuntimeTypeHandle)); var declaringType = GetDeclaringType(field.DeclaringType); IL.Emit(OpCodes.Ldtoken, field); IL.Emit(OpCodes.Ldtoken, declaringType); IL.Emit(OpCodes.Call, getFieldFromHandle); }
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); }
/// <summary> /// Pushes the current <paramref name="method"/> onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="method">The method that represents the <see cref="MethodInfo"/> that will be pushed onto the stack.</param> /// <param name="module">The module that contains the host method.</param> public static void PushMethod(this CilWorker IL, MethodReference method, ModuleDefinition module) { var getMethodFromHandle = module.ImportMethod<MethodBase>("GetMethodFromHandle", typeof (RuntimeMethodHandle), typeof (RuntimeTypeHandle)); var declaringType = method.DeclaringType; // Instantiate the generic type before determining // the current method if (declaringType.GenericParameters.Count > 0) { var genericType = new GenericInstanceType(declaringType); foreach (GenericParameter parameter in declaringType.GenericParameters) { genericType.GenericArguments.Add(parameter); } declaringType = genericType; } IL.Emit(OpCodes.Ldtoken, method); IL.Emit(OpCodes.Ldtoken, declaringType); IL.Emit(OpCodes.Call, getMethodFromHandle); }
/// <summary> /// Saves the generic type arguments that were used to construct the method. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="method">The target method whose generic type arguments (if any) will be saved into the <paramref name="typeArguments">local variable</paramref>.</param> /// <param name="module">The module that contains the host method.</param> /// <param name="typeArguments">The local variable that will store the resulting array of <see cref="Type"/> objects.</param> public static void PushGenericArguments(this CilWorker IL, IGenericParameterProvider method, ModuleDefinition module, VariableDefinition typeArguments) { var getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); var genericParameterCount = method.GenericParameters.Count; var genericParameters = method.GenericParameters; for (var index = 0; index < genericParameterCount; index++) { var current = genericParameters[index]; IL.Emit(OpCodes.Ldloc, typeArguments); IL.Emit(OpCodes.Ldc_I4, index); IL.Emit(OpCodes.Ldtoken, current); IL.Emit(OpCodes.Call, getTypeFromHandle); IL.Emit(OpCodes.Stelem_Ref); } }
/// <summary> /// Emits the instructions that introduce the <see cref="IContainerPlugin"/> instances to the current <see cref="IMicroContainer"/> instance. /// </summary> /// <param name="module">The target module.</param> /// <param name="dependencyContainer">The <see cref="IDependencyContainer"/> instance that contains the services that will be instantiated by compiled container.</param> /// <param name="il">The current <see cref="ILProcessor"/> instance that points to the current method body.</param> private void InitializeContainerPlugins(ModuleDefinition module, IDependencyContainer dependencyContainer, ILProcessor il) { var pluginDependencies = new List<IDependency>(dependencyContainer.Dependencies); Predicate<IDependency> predicate = dependency => { if (dependency.ServiceType != typeof(IContainerPlugin)) return false; var matches = dependencyContainer.GetImplementations(dependency, false); var matchList = new List<IImplementation>(matches); return matchList.Count > 0; }; pluginDependencies = pluginDependencies.FindAll(predicate); var getTypeFromHandleMethod = typeof(System.Type).GetMethod("GetTypeFromHandle", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); var getTypeFromHandle = module.Import(getTypeFromHandleMethod); var getInstanceMethod = module.ImportMethod<IMicroContainer>("GetInstance"); foreach (var currentDependency in pluginDependencies) { var currentType = module.Import(currentDependency.ServiceType); var serviceName = currentDependency.ServiceName; il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldtoken, currentType); il.Emit(OpCodes.Call, getTypeFromHandle); var loadString = serviceName == null ? il.Create(OpCodes.Ldnull) : il.Create(OpCodes.Ldstr, serviceName); il.Append(loadString); il.Emit(OpCodes.Callvirt, getInstanceMethod); il.Emit(OpCodes.Pop); } }
private static void InvokeInterceptor(ModuleDefinition module, CilWorker IL, VariableDefinition methodReplacement, TypeReference returnType, VariableDefinition invocationInfo) { var interceptMethod = module.ImportMethod<IInterceptor>("Intercept"); IL.Emit(OpCodes.Ldloc, methodReplacement); IL.Emit(OpCodes.Ldloc, invocationInfo); IL.Emit(OpCodes.Callvirt, interceptMethod); IL.PackageReturnValue(module, returnType); }
public override void ImportReferences(ModuleDefinition module) { _getCurrentMethod = module.ImportMethod<MethodBase>("GetCurrentMethod", BindingFlags.Public | BindingFlags.Static); _emitter.ImportReferences(module); }
/// <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) { 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> /// Pushes a <paramref name="Type"/> instance onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="type">The type that represents the <see cref="Type"/> that will be pushed onto the stack.</param> /// <param name="module">The module that contains the host method.</param> public static void PushType(this CilWorker IL, TypeReference type, ModuleDefinition module) { var getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle", typeof (RuntimeTypeHandle)); // Instantiate the generic type before pushing it onto the stack var declaringType = GetDeclaringType(type); IL.Emit(OpCodes.Ldtoken, declaringType); IL.Emit(OpCodes.Call, getTypeFromHandle); }
/// <summary> /// Saves the current method signature of a method into an array /// of <see cref="System.Type"/> objects. This can be used to determine the /// signature of methods with generic type parameters or methods that have /// parameters that are generic parameters specified by the type itself. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="method">The target method whose generic type arguments (if any) will be saved into the local variable .</param> /// <param name="module">The module that contains the host method.</param> /// <param name="parameterTypes">The local variable that will store the current method signature.</param> public static void SaveParameterTypes(this CilWorker IL, MethodReference method, ModuleDefinition module, VariableDefinition parameterTypes) { var getTypeFromHandle = module.ImportMethod<Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); var parameterCount = method.Parameters.Count; for (var index = 0; index < parameterCount; index++) { var current = method.Parameters[index]; IL.Emit(OpCodes.Ldloc, parameterTypes); IL.Emit(OpCodes.Ldc_I4, index); IL.Emit(OpCodes.Ldtoken, current.ParameterType); IL.Emit(OpCodes.Call, getTypeFromHandle); IL.Emit(OpCodes.Stelem_Ref); } }
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"); }
/// <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); } }