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