/// <summary> /// Compiles a dependency graph into an IOC container. /// </summary> /// <param name="dependencyContainer">The <see cref="IDependencyContainer"/> instance that contains the services that will be instantiated by compiled container.</param> /// <param name="typeName">The name of the <see cref="IMicroContainer"/> type.</param> /// <param name="namespaceName">The namespace name that will be associated with the container type.</param> /// <param name="assemblyName">The name of the assembly that will contain the container type.</param> /// <returns>An assembly containing the compiled IOC container.</returns> public AssemblyDefinition Compile(string typeName, string namespaceName, string assemblyName, IDependencyContainer dependencyContainer) { var containerType = _createContainerType.CreateContainerType(typeName, namespaceName, assemblyName); var module = containerType.Module; var assembly = module.Assembly; var hashEmitter = new ServiceHashEmitter(); var getServiceHash = hashEmitter.AddGetServiceHashMethodTo(containerType, false); var fieldType = module.Import(typeof(Dictionary <int, int>)); var fieldEmitter = new FieldBuilder(); var jumpTargetField = fieldEmitter.AddField(containerType, "__jumpTargets", fieldType); var serviceMap = _serviceMapBuilder.GetAvailableServices(dependencyContainer); var jumpTargets = new Dictionary <IDependency, int>(); // Map the switch labels in the default constructor AddJumpEntries(module, jumpTargetField, containerType, getServiceHash, serviceMap, jumpTargets); var defaultConstructor = containerType.GetDefaultConstructor(); var body = defaultConstructor.Body; var il = body.GetILProcessor(); AddInitializationMap(containerType, module, fieldEmitter); InitializeContainerPlugins(module, dependencyContainer, il); il.Emit(OpCodes.Ret); _containsMethodImplementor.DefineContainsMethod(containerType, module, getServiceHash, jumpTargetField); _getInstanceMethodImplementor.DefineGetInstanceMethod(containerType, module, getServiceHash, jumpTargetField, serviceMap); _getAllInstancesMethodImplementor.DefineGetAllInstancesMethod(containerType, module, serviceMap); // Remove the NextContainer property stub var targetMethods = new List <MethodDefinition>(); foreach (MethodDefinition method in containerType.Methods) { var methodName = method.Name; if (methodName == "get_NextContainer" || methodName == "set_NextContainer") { targetMethods.Add(method); } } targetMethods.ForEach(m => containerType.Methods.Remove(m)); // Add the NextContainer property containerType.AddProperty("NextContainer", typeof(IMicroContainer)); return(assembly); }
public void ShouldCreateJumpEntryFieldInTargetType() { var assembly = _assemblyBuilder.CreateAssembly(Guid.NewGuid().ToString(), ModuleKind.Dll); var module = assembly.MainModule; var objectType = module.ImportType(typeof(object)); var typeBuilder = new TypeBuilder(); TypeDefinition targetType = typeBuilder.CreateType(Guid.NewGuid().ToString(), "Test", objectType, assembly); var entryDictionaryType = module.ImportType <Dictionary <int, int> >(); var entryBuilder = new FieldBuilder(); var targetField = entryBuilder.AddField(targetType, "___jumpEntries", entryDictionaryType); // The type should have a field that is a Dictionary<int, int> Assert.IsNotNull(targetField); Assert.AreEqual(targetField.FieldType, entryDictionaryType); }
public static FieldBuilder Add(string name) => FieldBuilder.AddField(name);
/// <summary> /// Compiles a dependency graph into an IOC container. /// </summary> /// <param name="dependencyContainer">The <see cref="IDependencyContainer"/> instance that contains the services that will be instantiated by compiled container.</param> /// <param name="typeName">The name of the <see cref="IMicroContainer"/> type.</param> /// <param name="namespaceName">The namespace name that will be associated with the container type.</param> /// <param name="assemblyName">The name of the assembly that will contain the container type.</param> /// <returns>An assembly containing the compiled IOC container.</returns> public AssemblyDefinition Compile(string typeName, string namespaceName, string assemblyName, IDependencyContainer dependencyContainer) { var containerType = _createContainerType.CreateContainerType(typeName, namespaceName, assemblyName); var module = containerType.Module; var assembly = module.Assembly; var hashEmitter = new ServiceHashEmitter(); var getServiceHash = hashEmitter.AddGetServiceHashMethodTo(containerType, false); var fieldType = module.Import(typeof(Dictionary<int, int>)); var fieldEmitter = new FieldBuilder(); var jumpTargetField = fieldEmitter.AddField(containerType, "__jumpTargets", fieldType); var serviceMap = _serviceMapBuilder.GetAvailableServices(dependencyContainer); var jumpTargets = new Dictionary<IDependency, int>(); // Map the switch labels in the default constructor AddJumpEntries(module, jumpTargetField, containerType, getServiceHash, serviceMap, jumpTargets); var defaultConstructor = containerType.GetDefaultConstructor(); var body = defaultConstructor.Body; var il = body.GetILProcessor(); AddInitializationMap(containerType, module, fieldEmitter); InitializeContainerPlugins(module, dependencyContainer, il); il.Emit(OpCodes.Ret); _containsMethodImplementor.DefineContainsMethod(containerType, module, getServiceHash, jumpTargetField); _getInstanceMethodImplementor.DefineGetInstanceMethod(containerType, module, getServiceHash, jumpTargetField, serviceMap); _getAllInstancesMethodImplementor.DefineGetAllInstancesMethod(containerType, module, serviceMap); // Remove the NextContainer property stub var targetMethods = new List<MethodDefinition>(); foreach (MethodDefinition method in containerType.Methods) { var methodName = method.Name; if (methodName == "get_NextContainer" || methodName == "set_NextContainer") targetMethods.Add(method); } targetMethods.ForEach(m => containerType.Methods.Remove(m)); // Add the NextContainer property containerType.AddProperty("NextContainer", typeof(IMicroContainer)); return assembly; }