/// <summary> /// Initializes the proxy factory with the default values. /// </summary> public ProxyFactory() { // Use the forwarding proxy type by default ProxyBuilder = new SerializableProxyBuilder(); InterfaceExtractor = new InterfaceExtractor(); Cache = new ProxyCache(); }
public void InterfaceExtractorShouldReturnTheCorrectResults() { var baseType = typeof (SampleClass); var extractor = new InterfaceExtractor(); var interfaces = new HashSet<Type>(); extractor.GetInterfaces(baseType, interfaces); Assert.IsTrue(interfaces.Contains(typeof (ISampleService))); Assert.IsTrue(interfaces.Contains(typeof (ISampleGenericService<int>))); // The result list must only contain interface types var nonInterfaceTypes = from t in interfaces where !t.IsInterface select t; Assert.IsTrue(nonInterfaceTypes.Count() == 0); }
public int GetHashCode(ProxyCacheEntry obj) { var extractor = new InterfaceExtractor(); var types = new HashSet <Type>(obj.Interfaces); extractor.GetInterfaces(obj.BaseType, types); // HACK: Calculate the hash code // by XORing all the types together var baseType = obj.BaseType; var result = baseType.GetHashCode(); foreach (var type in types) { result ^= type.GetHashCode(); } return(result); }
/// <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); }