/// <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); }
/// <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> /// 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); }
/// <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); } }