/// <summary> /// Adds a default constructor to the singleton type. /// </summary> /// <param name="module">The module that will host the singleton type.</param> /// <param name="singletonName">The name of the singleton.</param> /// <param name="typeAttributes">The type attributes that describes the singleton type.</param> /// <param name="objectType">The object ty pe.</param> /// <returns>A <see cref="TypeDefinition"/> that represents the singleton type.</returns> private static TypeDefinition AddDefaultSingletonConstructor(ModuleDefinition module, string singletonName, TypeAttributes typeAttributes, TypeReference objectType) { // Add a default constructor and make it private var singletonType = module.DefineClass(singletonName, "Hiro.Containers.Internal", typeAttributes, objectType); singletonType.AddDefaultConstructor(); var constructor = singletonType.GetDefaultConstructor(); constructor.IsFamilyOrAssembly = true; return(singletonType); }
/// <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 TypeDefinition CreateType(string adapterName, string namespaceName, Dictionary <MethodReference, MethodReference> methodMap) { const TypeAttributes adapterAttributes = TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.BeforeFieldInit; var adapterType = _targetModule.DefineClass(adapterName, namespaceName, adapterAttributes, _targetModule.ImportType <object>()); var fieldName = string.Format("___<>{0}__BackingField", _targetDependency.Name); var targetField = new FieldDefinition(fieldName, _targetDependency, FieldAttributes.Private); adapterType.Fields.Add(targetField); adapterType.Interfaces.Add(_interfaceType); _addAdapterConstructor.AddConstructor(adapterType, targetField); foreach (var method in _interfaceType.Methods.Cast <MethodDefinition>()) { _addAdapterMethod.AddMethod(adapterType, targetField, method, methodMap); } return(adapterType); }
/// <summary> /// Creates a proxy type using the given /// <paramref name="baseType"/> as the base class /// and ensures that the proxy type implements the given /// interface types. /// </summary> /// <param name="baseType">The base class from which the proxy type will be derived.</param> /// <param name="baseInterfaces">The list of interfaces that the proxy will implement.</param> /// <returns>A forwarding proxy.</returns> public Type CreateProxyType(Type baseType, IEnumerable <Type> baseInterfaces) { // Reuse the cached results, if possible Type[] originalInterfaces = baseInterfaces.ToArray(); if (Cache != null && Cache.Contains(baseType, originalInterfaces)) { return(Cache.Get(baseType, originalInterfaces)); } if (!baseType.IsPublic) { throw new ArgumentException("The proxy factory can only generate proxies from public base classes.", "baseType"); } bool hasNonPublicInterfaces = (from t in baseInterfaces where t.IsNotPublic select t).Count() > 0; if (hasNonPublicInterfaces) { throw new ArgumentException("The proxy factory cannot generate proxies from non-public interfaces.", "baseInterfaces"); } #region Determine which interfaces need to be implemented Type actualBaseType = baseType.IsInterface ? typeof(object) : baseType; var interfaces = new HashSet <Type>(baseInterfaces); // Move the base type into the list of interfaces // if the user mistakenly entered // an interface type as the base type if (baseType.IsInterface) { interfaces.Add(baseType); } if (InterfaceExtractor != null) { // Get the interfaces for the base type InterfaceExtractor.GetInterfaces(actualBaseType, interfaces); Type[] targetList = interfaces.ToArray(); // Extract the inherited interfaces foreach (Type type in targetList) { InterfaceExtractor.GetInterfaces(type, interfaces); } } #endregion #region Generate the assembly string assemblyName = "LinFu.Proxy"; AssemblyDefinition assembly = AssemblyFactory.DefineAssembly(assemblyName, AssemblyKind.Dll); ModuleDefinition mainModule = assembly.MainModule; TypeReference importedBaseType = mainModule.Import(actualBaseType); TypeAttributes attributes = TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit; #endregion #region Initialize the proxy type string guid = Guid.NewGuid().ToString().Replace("-", ""); string typeName = string.Format("{0}Proxy-{1}", baseType.Name, guid); string namespaceName = "LinFu.Proxy"; TypeDefinition proxyType = mainModule.DefineClass(typeName, namespaceName, attributes, importedBaseType); proxyType.AddDefaultConstructor(); #endregion if (ProxyBuilder == null) { throw new NullReferenceException("The 'ProxyBuilder' property cannot be null"); } // Add the list of interfaces to the target type foreach (Type interfaceType in interfaces) { if (!interfaceType.IsInterface) { continue; } TypeReference currentType = mainModule.Import(interfaceType); proxyType.Interfaces.Add(currentType); } // Hand it off to the builder for construction ProxyBuilder.Construct(actualBaseType, interfaces, mainModule, proxyType); // Verify the assembly, if possible if (Verifier != null) { Verifier.Verify(assembly); } #region Compile the results Assembly compiledAssembly = assembly.ToAssembly(); IEnumerable <Type> types = null; try { types = compiledAssembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } Type result = (from t in types where t != null && t.IsClass select t).FirstOrDefault(); #endregion // Cache the result if (Cache != null) { Cache.Store(result, baseType, originalInterfaces); } return(result); }