Inheritance: IExtractInterfaces
示例#1
0
 /// <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();
 }
 /// <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();
 }
示例#3
0
        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);
        }
示例#4
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);
            }
示例#5
0
        /// <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);
        }