/// <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 ShouldBeAbleToCreatePrivateStaticGetServiceHashCodeMethodForAGivenType() { var assembly = _assemblyBuilder.CreateAssembly(Guid.NewGuid().ToString(), ModuleKind.Dll); var module = assembly.MainModule; TypeReference baseType = module.Import(typeof(object)); var typeBuilder = new TypeBuilder(); var newType = typeBuilder.CreateType("Test", "Test", baseType, assembly); var emitter = new ServiceHashEmitter(); emitter.AddGetServiceHashMethodTo(newType, true); var result = (from MethodDefinition m in newType.Methods where m.Name == "GetServiceHashCode" select m).First(); Assert.IsNotNull(result); // Load the assembly var loadedAssembly = assembly.ToAssembly(); var containerType = loadedAssembly.GetTypes()[0]; var targetMethod = containerType.GetMethod("GetServiceHashCode", BindingFlags.Public | BindingFlags.Static); Assert.IsNotNull(targetMethod); var serviceName = "Test"; var serviceType = typeof(IVehicle); // The GetServiceHashCode method result should match the actual hash var expectedHash = serviceName.GetHashCode() ^ serviceType.GetHashCode(); var actualHash = targetMethod.Invoke(null, new object[] { serviceType, serviceName }); Assert.AreEqual(expectedHash, actualHash); }