/// <summary> /// Creates an un-cached proxy class. /// </summary> /// <param name="baseType"> /// The base <see cref="Type"/> to proxy. /// </param> /// <returns> /// The proxy <see cref="Type"/>. /// </returns> private Type CreateUncachedProxyType(Type baseType) { // Create a dynamic assembly and module to store the proxy. AppDomain currentDomain = AppDomain.CurrentDomain; string typeName = string.Format("{0}Proxy", baseType.Name); string assemblyName = string.Format("{0}Assembly", typeName); string moduleName = string.Format("{0}Module", typeName); // Define different behaviors for debug and release so that we can make debugging easier. AssemblyName name = new AssemblyName(assemblyName); #if DEBUG AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName, string.Format("{0}.mod", moduleName), true); #else AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName); #endif // Define type attributes const TypeAttributes TypeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit; // Define the type. TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes, baseType); // Emit the default constructors for this proxy so that classes without parameterless constructors // can be proxied. ConstructorInfo[] constructors = baseType.GetConstructors(); foreach (ConstructorInfo constructorInfo in constructors) { ConstructorEmitter.Emit(typeBuilder, constructorInfo); } // Emit the IProxy IInterceptor property. FieldInfo interceptorField = InterceptorEmitter.Emit(typeBuilder); // Emit each property that is to be intercepted. MethodInfo[] methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.Instance); IEnumerable <MethodInfo> proxyList = this.BuildPropertyList(methods); foreach (MethodInfo methodInfo in proxyList) { PropertyEmitter.Emit(typeBuilder, methodInfo, interceptorField); } // Create and return. return(typeBuilder.CreateType()); }
/// <summary> /// Creates an un-cached proxy class. /// </summary> /// <param name="baseType">The base <see cref="Type"/> to proxy.</param> /// <param name="properties">The collection of property names to map.</param> /// <returns> /// The proxy <see cref="Type"/>. /// </returns> private Type CreateUncachedProxyType(Type baseType, IEnumerable <string> properties) { // Create a dynamic assembly and module to store the proxy. AppDomain currentDomain = AppDomain.CurrentDomain; string typeName = $"{baseType.Name}Proxy"; string assemblyName = $"{typeName}Assembly"; string moduleName = $"{typeName}Module"; // Define different behaviors for debug and release so that we can make debugging easier. var name = new AssemblyName(assemblyName); AssemblyBuilder assemblyBuilder; #if DEBUG assemblyBuilder = currentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName, $"{moduleName}.mod", true); // Add a debuggable attribute to the assembly saying to disable optimizations Type daType = typeof(DebuggableAttribute); ConstructorInfo daCtor = daType.GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) }); var daBuilder = new CustomAttributeBuilder( daCtor, new object[] { DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default }); assemblyBuilder.SetCustomAttribute(daBuilder); #else assemblyBuilder = currentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName); #endif // Define type attributes const TypeAttributes typeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit; // Define the type. TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, baseType); // Emit the default constructors for this proxy so that classes without parameterless constructors // can be proxied. ConstructorInfo[] constructors = baseType.GetConstructors(); foreach (ConstructorInfo constructorInfo in constructors) { ConstructorEmitter.Emit(typeBuilder, constructorInfo); } // Emit the IProxy IInterceptor property. FieldInfo interceptorField = InterceptorEmitter.Emit(typeBuilder); // Collect and filter our list of properties to intercept. MethodInfo[] methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.Instance); IEnumerable <MethodInfo> proxyList = this.BuildPropertyList(methods) .Where(m => properties.Contains(m.Name.Substring(4), StringComparer.OrdinalIgnoreCase)); // Emit each property that is to be intercepted. foreach (MethodInfo methodInfo in proxyList) { PropertyEmitter.Emit(typeBuilder, methodInfo, interceptorField); } // Create and return. Type result = typeBuilder.CreateType(); #if DEBUG assemblyBuilder.Save(typeName + ".dll"); #endif return(result); }