private Type GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options) { var scope = emitter.ModuleScope; Type[] invocationInterfaces; if (canChangeTarget) { invocationInterfaces = new[] { typeof(IInvocation), typeof(IChangeProxyTarget) }; } else { invocationInterfaces = new[] { typeof(IInvocation) }; } var key = new CacheKey(method.Method, CompositionInvocationTypeGenerator.BaseType, invocationInterfaces, null); // no locking required as we're already within a lock var invocation = scope.GetFromCache(key); if (invocation != null) { return invocation; } invocation = new CompositionInvocationTypeGenerator(method.Method.DeclaringType, method, method.Method, canChangeTarget, null) .Generate(emitter, options, namingScope) .BuildType(); scope.RegisterInCache(key, invocation); return invocation; }
public Type GenerateCode(Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); interfaces = TypeUtil.GetAllInterfaces(interfaces); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); ProxyGenerationOptions = options; var cacheKey = new CacheKey(targetType, interfaces, options); return ObtainProxyType(cacheKey, (n, s) => GenerateType(n, interfaces, s)); }
private Type GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options) { ModuleScope scope = emitter.ModuleScope; CacheKey key = new CacheKey(method.Method, WCFCompositionInvocationTypeGenerator.BaseType, null, null); Type invocation = scope.GetFromCache(key); if (invocation == null) { invocation = new WCFCompositionInvocationTypeGenerator(method.Method.DeclaringType, method, method.Method, false, null).Generate(emitter, options, base.namingScope).BuildType(); scope.RegisterInCache(key, invocation); } return invocation; }
public void InstanceEquivalence() { CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass), null, ProxyGenerationOptions.Default); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass), null, ProxyGenerationOptions.Default); Assert.AreEqual(key1, key2); key1 = new CacheKey(typeof (NonPublicConstructorClass), null, ProxyGenerationOptions.Default); key2 = new CacheKey(typeof (NonPublicConstructorClass), null, new ProxyGenerationOptions()); Assert.AreEqual(key1, key2); }
public void InstanceEquivalence_WithInterfaces() { CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass), new Type[0], ProxyGenerationOptions.Default); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass), new Type[0], ProxyGenerationOptions.Default); Assert.AreEqual(key1, key2); key1 = new CacheKey(typeof (NonPublicConstructorClass), new Type[] {typeof (IDisposable)}, ProxyGenerationOptions.Default); key2 = new CacheKey(typeof (NonPublicConstructorClass), new Type[] {typeof (IDisposable)}, ProxyGenerationOptions.Default); Assert.AreEqual(key1, key2); }
public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType"); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); EnsureValidBaseType(options.BaseTypeForInterfaceProxy); ProxyGenerationOptions = options; interfaces = TypeUtil.GetAllInterfaces(interfaces).ToArray(); var cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options); return ObtainProxyType(cacheKey, (n, s) => GenerateType(n, proxyTargetType, interfaces, s)); }
public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType"); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); EnsureValidBaseType(options.BaseTypeForInterfaceProxy); Type proxyType; interfaces = TypeUtil.GetAllInterfaces(interfaces).ToArray(); CacheKey cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options); using (var locker = Scope.Lock.ForReadingUpgradeable()) { Type cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.Debug("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Upgrade the lock to a write lock, then read again. This is to avoid generating duplicate types // under heavy multithreaded load. locker.Upgrade(); cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.Debug("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Log details about the cache miss Logger.Debug("No cached proxy type was found for target type {0}.", targetType.FullName); EnsureOptionsOverrideEqualsAndGetHashCode(options); ProxyGenerationOptions = options; var name = Scope.NamingScope.GetUniqueName("Castle.Proxies." + targetType.Name + "Proxy"); proxyType = GenerateType(name, proxyTargetType, interfaces, Scope.NamingScope.SafeSubScope()); AddToCache(cacheKey, proxyType); } return proxyType; }
public void DifferentOptions() { ProxyGenerationOptions options1 = new ProxyGenerationOptions(); ProxyGenerationOptions options2 = new ProxyGenerationOptions(); options1.BaseTypeForInterfaceProxy = typeof (IConvertible); CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass), null, options1); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass), null, options2); Assert.AreNotEqual(key1, key2); options1 = new ProxyGenerationOptions(); options2 = new ProxyGenerationOptions(); options2.Selector = new AllInterceptorSelector(); key1 = new CacheKey(typeof (NonPublicConstructorClass), null, options1); key2 = new CacheKey(typeof (NonPublicConstructorClass), null, options2); Assert.AreNotEqual(key1, key2); }
public void DifferentKeys() { CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass), null, ProxyGenerationOptions.Default); CacheKey key2 = new CacheKey(typeof (NonPublicMethodsClass), null, ProxyGenerationOptions.Default); Assert.AreNotEqual(key1, key2); key1 = new CacheKey(typeof (NonPublicConstructorClass), new Type[] {typeof (IDisposable)}, ProxyGenerationOptions.Default); key2 = new CacheKey(typeof (NonPublicConstructorClass), new Type[] {typeof (IConvertible)}, ProxyGenerationOptions.Default); Assert.AreNotEqual(key1, key2); key1 = new CacheKey(typeof (NonPublicConstructorClass), new Type[] {typeof (IDisposable)}, ProxyGenerationOptions.Default); key2 = new CacheKey(typeof (NonPublicMethodsClass), new Type[] {typeof (IDisposable)}, ProxyGenerationOptions.Default); Assert.AreNotEqual(key1, key2); }
private Type GetInvocationType(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options) { Type[] invocationInterfaces; ModuleScope scope = @class.ModuleScope; if (this.canChangeTarget) { invocationInterfaces = new Type[] { typeof(IInvocation), typeof(IChangeProxyTarget) }; } else { invocationInterfaces = new Type[] { typeof(IInvocation) }; } CacheKey key = new CacheKey(method.Method, WCFCompositionInvocationTypeGenerator.BaseType, invocationInterfaces, null); Type invocation = scope.GetFromCache(key); if (invocation == null) { invocation = new WCFCompositionInvocationTypeGenerator(method.Method.DeclaringType, method, method.Method, this.canChangeTarget, null).Generate(@class, options, base.namingScope).BuildType(); scope.RegisterInCache(key, invocation); } return invocation; }
private Type GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options) { var scope = emitter.ModuleScope; var key = new CacheKey(method.Method, InterfaceInvocationTypeGenerator.BaseType, null, null); // no locking required as we're already within a lock var invocation = scope.GetFromCache(key); if (invocation != null) { return invocation; } invocation = new InterfaceInvocationTypeGenerator(method.Method.DeclaringType, method, method.Method, false) .Generate(emitter, options, namingScope).BuildType(); scope.RegisterInCache(key, invocation); return invocation; }
public Type GetGeneratedType() { Type proxyType; var cacheKey = new CacheKey(targetType, additionalInterfacesToProxy, ProxyGenerationOptions); using (var locker = Scope.Lock.ForReadingUpgradeable()) { var cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.Debug("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Upgrade the lock to a write lock, then read again. This is to avoid generating duplicate types // under heavy multithreaded load. locker.Upgrade(); cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.Debug("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Log details about the cache miss Logger.Debug("No cached proxy type was found for target type {0}.", targetType.FullName); EnsureOptionsOverrideEqualsAndGetHashCode(ProxyGenerationOptions); var name = Scope.NamingScope.GetUniqueName("Castle.Proxies." + targetType.Name + "Proxy"); proxyType = GenerateType(name, Scope.NamingScope.SafeSubScope()); AddToCache(cacheKey, proxyType); } return proxyType; }
protected Type GetFromCache(CacheKey key) { return scope.GetFromCache(key); }
/// <summary> /// Returns a type from this scope's type cache, or null if the key cannot be found. /// </summary> /// <param name="key">The key to be looked up in the cache.</param> /// <returns>The type from this scope's type cache matching the key, or null if the key cannot be found</returns> public Type GetFromCache (CacheKey key) { // no lock needed, typeCache is synchronized return (Type) typeCache[key]; }
/// <summary> /// Registers a type in this scope's type cache. /// </summary> /// <param name="key">The key to be associated with the type.</param> /// <param name="type">The type to be stored in the cache.</param> public void RegisterInCache (CacheKey key, Type type) { // no lock needed, typeCache is synchronized typeCache[key] = type; }
protected Type ObtainProxyType(CacheKey cacheKey, Func<string, INamingScope, Type> factory) { using (var locker = Scope.Lock.ForReadingUpgradeable()) { var cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.DebugFormat("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Upgrade the lock to a write lock, then read again. This is to avoid generating duplicate types // under heavy multithreaded load. locker.Upgrade(); cacheType = GetFromCache(cacheKey); if (cacheType != null) { Logger.DebugFormat("Found cached proxy type {0} for target type {1}.", cacheType.FullName, targetType.FullName); return cacheType; } // Log details about the cache miss Logger.DebugFormat("No cached proxy type was found for target type {0}.", targetType.FullName); EnsureOptionsOverrideEqualsAndGetHashCode(ProxyGenerationOptions); var name = Scope.NamingScope.GetUniqueName("Castle.Proxies." + targetType.Name + "Proxy"); var proxyType = factory.Invoke(name, Scope.NamingScope.SafeSubScope()); AddToCache(cacheKey, proxyType); return proxyType; } }
private Type GetInvocationType(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options) { var scope = @class.ModuleScope; var invocationInterfaces = new[] { typeof(IInvocation) }; var key = new CacheKey(method.Method, CompositionInvocationTypeGenerator.BaseType, invocationInterfaces, null); // no locking required as we're already within a lock var invocation = scope.GetFromCache(key); if (invocation != null) { return invocation; } invocation = BuildInvocationType(method, @class, options); scope.RegisterInCache(key, invocation); return invocation; }
public Type GetProxyType() { var cacheKey = new CacheKey(targetType, null, null); return ObtainProxyType(cacheKey, GenerateType); }
public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType"); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); Type generatedType; ReaderWriterLock rwlock = Scope.RWLock; rwlock.AcquireReaderLock(-1); CacheKey cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options); Type cacheType = GetFromCache(cacheKey); if (cacheType != null) { rwlock.ReleaseReaderLock(); return cacheType; } rwlock.UpgradeToWriterLock(-1); try { cacheType = GetFromCache(cacheKey); if (cacheType != null) { return cacheType; } SetGenerationOptions (options); String newName = targetType.Name + "Proxy" + Guid.NewGuid().ToString("N"); // Add Interfaces that the proxy implements ArrayList interfaceList = new ArrayList(); interfaceList.Add(targetType); if (interfaces != null) { interfaceList.AddRange(interfaces); } if (!interfaceList.Contains(typeof(ISerializable))) interfaceList.Add(typeof(ISerializable)); AddMixinInterfaces(interfaceList); AddDefaultInterfaces(interfaceList); Type baseType = options.BaseTypeForInterfaceProxy; ClassEmitter emitter = BuildClassEmitter(newName, baseType, interfaceList); CreateOptionsField (emitter); emitter.DefineCustomAttribute(new XmlIncludeAttribute(targetType)); emitter.DefineCustomAttribute(new SerializableAttribute()); // Custom attributes ReplicateNonInheritableAttributes(targetType, emitter); // Fields generations FieldReference interceptorsField = emitter.CreateField("__interceptors", typeof(IInterceptor[])); targetField = emitter.CreateField("__target", proxyTargetType); emitter.DefineCustomAttributeFor(interceptorsField, new XmlIgnoreAttribute()); emitter.DefineCustomAttributeFor(targetField, new XmlIgnoreAttribute()); // Implement builtin Interfaces ImplementProxyTargetAccessor(targetType, emitter,interceptorsField); // Collect methods PropertyToGenerate[] propsToGenerate; EventToGenerate[] eventToGenerates; MethodInfo[] methods = CollectMethodsAndProperties(emitter, targetType, out propsToGenerate, out eventToGenerates); if (interfaces != null && interfaces.Length != 0) { ArrayList tmpInterfaces = new ArrayList(interfaces); foreach(Type inter in interfaces) { if (inter.IsAssignableFrom(proxyTargetType)) { PropertyToGenerate[] tempPropsToGenerate; EventToGenerate[] tempEventToGenerates; MethodInfo[] methodsTemp = CollectMethodsAndProperties(emitter, inter, out tempPropsToGenerate, out tempEventToGenerates); PropertyToGenerate[] newPropsToGenerate = new PropertyToGenerate[tempPropsToGenerate.Length + propsToGenerate.Length]; MethodInfo[] newMethods = new MethodInfo[methodsTemp.Length + methods.Length]; EventToGenerate[] newEvents = new EventToGenerate[eventToGenerates.Length + tempEventToGenerates.Length]; Array.Copy(methods, newMethods, methods.Length); Array.Copy(methodsTemp, 0, newMethods, methods.Length, methodsTemp.Length); Array.Copy(propsToGenerate, newPropsToGenerate, propsToGenerate.Length); Array.Copy(tempPropsToGenerate, 0, newPropsToGenerate, propsToGenerate.Length, tempPropsToGenerate.Length); Array.Copy(eventToGenerates, newEvents, eventToGenerates.Length); Array.Copy(tempEventToGenerates, 0, newEvents, eventToGenerates.Length, tempEventToGenerates.Length); methods = newMethods; propsToGenerate = newPropsToGenerate; eventToGenerates = newEvents; tmpInterfaces.Remove(inter); } } interfaces = (Type[]) tmpInterfaces.ToArray(typeof(Type)); } RegisterMixinMethodsAndProperties(emitter, ref methods, ref propsToGenerate, ref eventToGenerates); options.Hook.MethodsInspected(); // Constructor ConstructorEmitter typeInitializer = GenerateStaticConstructor(emitter); if (!proxyTargetType.IsInterface) { CacheMethodTokens(emitter, MethodFinder.GetAllInstanceMethods(proxyTargetType, BindingFlags.Public | BindingFlags.Instance), typeInitializer); } CreateInitializeCacheMethodBody(proxyTargetType, methods, emitter, typeInitializer); FieldReference[] mixinFields = AddMixinFields(emitter); List<FieldReference> fields = new List<FieldReference>(mixinFields); fields.Add(interceptorsField); fields.Add(targetField); GenerateConstructors(emitter, baseType, fields.ToArray()); // GenerateParameterlessConstructor(emitter, interceptorsField, baseType); // Implement interfaces if (interfaces != null && interfaces.Length != 0) { foreach(Type inter in interfaces) { ImplementBlankInterface(targetType, inter, emitter, interceptorsField, typeInitializer); } } // Create invocation types foreach(MethodInfo method in methods) { CreateInvocationForMethod(emitter, method, proxyTargetType); } // Create methods overrides Dictionary<MethodInfo, MethodEmitter> method2Emitter = new Dictionary<MethodInfo, MethodEmitter>(); foreach(MethodInfo method in methods) { if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_") || method.Name.StartsWith("add_") || method.Name.StartsWith("remove_")) || methodsToSkip.Contains(method)) { continue; } NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[method]; MethodEmitter newProxiedMethod = CreateProxiedMethod( targetType, method, emitter, nestedClass, interceptorsField, GetTargetRef(method, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[method]); ReplicateNonInheritableAttributes(method, newProxiedMethod); method2Emitter[method] = newProxiedMethod; } foreach(PropertyToGenerate propToGen in propsToGenerate) { if (propToGen.CanRead) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.GetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.GetMethod); MethodEmitter getEmitter = propToGen.Emitter.CreateGetMethod(atts); ImplementProxiedMethod(targetType, getEmitter, propToGen.GetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.GetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.GetMethod]); ReplicateNonInheritableAttributes(propToGen.GetMethod, getEmitter); // emitter.TypeBuilder.DefineMethodOverride(getEmitter.MethodBuilder, propToGen.GetMethod); } if (propToGen.CanWrite) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.SetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.SetMethod); MethodEmitter setEmitter = propToGen.Emitter.CreateSetMethod(atts); ImplementProxiedMethod(targetType, setEmitter, propToGen.SetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.SetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.SetMethod]); ReplicateNonInheritableAttributes(propToGen.SetMethod, setEmitter); // emitter.TypeBuilder.DefineMethodOverride(setEmitter.MethodBuilder, propToGen.SetMethod); } } foreach(EventToGenerate eventToGenerate in eventToGenerates) { NestedClassEmitter add_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.AddMethod]; MethodAttributes add_atts = ObtainMethodAttributes(eventToGenerate.AddMethod); MethodEmitter addEmitter = eventToGenerate.Emitter.CreateAddMethod(add_atts); ImplementProxiedMethod(targetType, addEmitter, eventToGenerate.AddMethod, emitter, add_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.AddMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.AddMethod]); ReplicateNonInheritableAttributes(eventToGenerate.AddMethod, addEmitter); NestedClassEmitter remove_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.RemoveMethod]; MethodAttributes remove_atts = ObtainMethodAttributes(eventToGenerate.RemoveMethod); MethodEmitter removeEmitter = eventToGenerate.Emitter.CreateRemoveMethod(remove_atts); ImplementProxiedMethod(targetType, removeEmitter, eventToGenerate.RemoveMethod, emitter, remove_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.RemoveMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.RemoveMethod]); ReplicateNonInheritableAttributes(eventToGenerate.RemoveMethod, removeEmitter); } ImplementGetObjectData(emitter, interceptorsField, mixinFields, interfaces); // Complete Initialize CompleteInitCacheMethod(typeInitializer.CodeBuilder); // Crosses fingers and build type generatedType = emitter.BuildType(); InitializeStaticFields (generatedType); /*foreach (MethodInfo m in TypeFinder.GetMethods(generatedType, BindingFlags.Instance | BindingFlags.Public)) { ParameterInfo[] parameters = m.GetParameters(); // Console.WriteLine(m.Name); for (int i = 0; i < parameters.Length; i++) { ParameterInfo paramInfo = parameters[i]; // Console.WriteLine("{0} {1} {2} {3}", paramInfo.Name, paramInfo.ParameterType, paramInfo.Attributes, paramInfo.Position); // Console.WriteLine("{0} {1} {2} {3}", paramInfo2.Name, paramInfo2.ParameterType, paramInfo2.Attributes, paramInfo2.Position); } } */ AddToCache(cacheKey, generatedType); } finally { rwlock.ReleaseWriterLock(); } return generatedType; }
public Type GenerateCode(Type[] interfaces, ProxyGenerationOptions options) { CheckNotGenericTypeDefinitions(interfaces, "interfaces"); Type type; ReaderWriterLock rwlock = Scope.RWLock; rwlock.AcquireReaderLock(-1); CacheKey cacheKey = new CacheKey(targetType, interfaces, options); Type cacheType = GetFromCache(cacheKey); if (cacheType != null) { rwlock.ReleaseReaderLock(); return cacheType; } rwlock.UpgradeToWriterLock(-1); try { cacheType = GetFromCache(cacheKey); if (cacheType != null) { return cacheType; } String newName = targetType.Name + "Proxy" + Guid.NewGuid().ToString("N"); // Add Interfaces that the proxy implements ArrayList interfaceList = new ArrayList(); if (interfaces != null) { interfaceList.AddRange(interfaces); } AddDefaultInterfaces(interfaceList); if (targetType.IsSerializable) { delegateToBaseGetObjectData = VerifyIfBaseImplementsGetObjectData(targetType); if (!interfaceList.Contains(typeof(ISerializable))) { interfaceList.Add(typeof(ISerializable)); } } ClassEmitter emitter = BuildClassEmitter(newName, targetType, interfaceList); SetGenerationOptions (options, emitter); emitter.DefineCustomAttribute(new XmlIncludeAttribute(targetType)); // Custom attributes ReplicateNonInheritableAttributes(targetType, emitter); // Fields generations FieldReference interceptorsField = emitter.CreateField("__interceptors", typeof(IInterceptor[])); // Implement builtin Interfaces ImplementProxyTargetAccessor(targetType, emitter,interceptorsField); emitter.DefineCustomAttributeFor(interceptorsField, new XmlIgnoreAttribute()); // Collect methods PropertyToGenerate[] propsToGenerate; EventToGenerate[] eventToGenerates; MethodInfo[] methods = CollectMethodsAndProperties(emitter, targetType, out propsToGenerate, out eventToGenerates); options.Hook.MethodsInspected(); // Constructor ConstructorEmitter typeInitializer = GenerateStaticConstructor(emitter); CreateInitializeCacheMethodBody(targetType, methods, emitter, typeInitializer); GenerateConstructors(emitter, targetType, interceptorsField); GenerateParameterlessConstructor(emitter, targetType, interceptorsField); if (delegateToBaseGetObjectData) { GenerateSerializationConstructor(emitter, interceptorsField, delegateToBaseGetObjectData); } // Implement interfaces if (interfaces != null && interfaces.Length != 0) { foreach(Type inter in interfaces) { ImplementBlankInterface(targetType, inter, emitter, interceptorsField, typeInitializer); } } // Create callback methods Dictionary<MethodInfo, MethodBuilder> method2Callback = new Dictionary<MethodInfo, MethodBuilder>(); foreach(MethodInfo method in methods) { method2Callback[method] = CreateCallbackMethod(emitter, method, method); } // Create invocation types Dictionary<MethodInfo, NestedClassEmitter> method2Invocation = new Dictionary<MethodInfo, NestedClassEmitter>(); foreach(MethodInfo method in methods) { MethodBuilder callbackMethod = method2Callback[method]; method2Invocation[method] = BuildInvocationNestedType(emitter, targetType, emitter.TypeBuilder, method, callbackMethod, ConstructorVersion.WithoutTargetMethod); } // Create methods overrides Dictionary<MethodInfo, MethodEmitter> method2Emitter = new Dictionary<MethodInfo, MethodEmitter>(); foreach(MethodInfo method in methods) { if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_") || method.Name.StartsWith("add_") || method.Name.StartsWith("remove_")) || methodsToSkip.Contains(method)) { continue; } NestedClassEmitter nestedClass = method2Invocation[method]; MethodEmitter newProxiedMethod = CreateProxiedMethod( targetType, method, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(method, newProxiedMethod); method2Emitter[method] = newProxiedMethod; } foreach(PropertyToGenerate propToGen in propsToGenerate) { if (propToGen.CanRead) { NestedClassEmitter nestedClass = method2Invocation[propToGen.GetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.GetMethod); MethodEmitter getEmitter = propToGen.Emitter.CreateGetMethod(atts); ImplementProxiedMethod(targetType, getEmitter, propToGen.GetMethod, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(propToGen.GetMethod, getEmitter); } if (propToGen.CanWrite) { NestedClassEmitter nestedClass = method2Invocation[propToGen.SetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.SetMethod); MethodEmitter setEmitter = propToGen.Emitter.CreateSetMethod(atts); ImplementProxiedMethod(targetType, setEmitter, propToGen.SetMethod, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(propToGen.SetMethod, setEmitter); } } foreach(EventToGenerate eventToGenerate in eventToGenerates) { NestedClassEmitter add_nestedClass = method2Invocation[eventToGenerate.AddMethod]; MethodAttributes add_atts = ObtainMethodAttributes(eventToGenerate.AddMethod); MethodEmitter addEmitter = eventToGenerate.Emitter.CreateAddMethod(add_atts); ImplementProxiedMethod(targetType, addEmitter, eventToGenerate.AddMethod, emitter, add_nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(eventToGenerate.AddMethod, addEmitter); NestedClassEmitter remove_nestedClass = method2Invocation[eventToGenerate.RemoveMethod]; MethodAttributes remove_atts = ObtainMethodAttributes(eventToGenerate.RemoveMethod); MethodEmitter removeEmitter = eventToGenerate.Emitter.CreateRemoveMethod(remove_atts); ImplementProxiedMethod(targetType, removeEmitter, eventToGenerate.RemoveMethod, emitter, remove_nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(eventToGenerate.RemoveMethod, removeEmitter); } ImplementGetObjectData(emitter, interceptorsField, interfaces); // Complete type initializer code body CompleteInitCacheMethod(typeInitializer.CodeBuilder); // Build type type = emitter.BuildType(); InitializeStaticFields (type); AddToCache(cacheKey, type); } finally { rwlock.ReleaseWriterLock(); } Scope.SaveAssembly(); return type; }
public Type GetGeneratedType() { var cacheKey = new CacheKey(targetType, targetType, additionalInterfacesToProxy, ProxyGenerationOptions); return ObtainProxyType(cacheKey, GenerateType); }
/// <summary> /// Registers a type in this scope's type cache. /// </summary> /// <param name = "key">The key to be associated with the type.</param> /// <param name = "type">The type to be stored in the cache.</param> public void RegisterInCache(CacheKey key, Type type) { typeCache[key] = type; }
private Type GetDelegateType(MetaMethod method, ClassEmitter @class, ProxyGenerationOptions options) { var scope = @class.ModuleScope; var key = new CacheKey( typeof(Delegate), targetType, new[] { method.MethodOnTarget.ReturnType } .Concat(ArgumentsUtil.GetTypes(method.MethodOnTarget.GetParameters())). ToArray(), null); var type = scope.GetFromCache(key); if (type != null) return type; type = new DelegateTypeGenerator(method, targetType) .Generate(@class, options, namingScope) .BuildType(); scope.RegisterInCache(key, type); return type; }
protected void AddToCache(CacheKey key, Type type) { scope.RegisterInCache(key, type); }
public void EqualWithProxyForType() { CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass).GetTypeInfo(), null, null, ProxyGenerationOptions.Default); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass).GetTypeInfo(), null, null, ProxyGenerationOptions.Default); Assert.AreEqual(key1, key2); CacheKey key3 = new CacheKey(null, null, null, ProxyGenerationOptions.Default); Assert.AreNotEqual(key1, key3); Assert.AreNotEqual(key3, key1); CacheKey key4 = new CacheKey(null, null, null, ProxyGenerationOptions.Default); Assert.AreEqual(key4, key3); Assert.AreEqual(key3, key4); }
public void EqualNullAndEmptyInterfaces() { CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass).GetTypeInfo(), null, null, ProxyGenerationOptions.Default); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass).GetTypeInfo(), null, Type.EmptyTypes, ProxyGenerationOptions.Default); Assert.AreEqual(key1, key2); Assert.AreEqual(key2, key1); }
public void CacheMappingsHoldTypes() { var scope = new ModuleScope(true); var builder = new DefaultProxyBuilder(scope); var cp = builder.CreateClassProxyType(typeof (object), Type.EmptyTypes, ProxyGenerationOptions.Default); var savedPath = scope.SaveAssembly(); CrossAppDomainCaller.RunInOtherAppDomain(delegate(object[] args) { var assembly = Assembly.LoadFrom((string) args[0]); var attribute = (CacheMappingsAttribute) assembly.GetCustomAttributes(typeof (CacheMappingsAttribute), false)[0]; var entries = attribute.GetDeserializedMappings(); Assert.AreEqual(1, entries.Count); var key = new CacheKey(typeof (object), new Type[0], ProxyGenerationOptions.Default); Assert.IsTrue(entries.ContainsKey(key)); Assert.AreEqual(args[1], entries[key]); }, savedPath, cp.FullName); File.Delete(savedPath); }
public void EquivalentOptions() { ProxyGenerationOptions options1 = new ProxyGenerationOptions(); ProxyGenerationOptions options2 = new ProxyGenerationOptions(); CacheKey key1 = new CacheKey(typeof (NonPublicConstructorClass), null, options1); CacheKey key2 = new CacheKey(typeof (NonPublicConstructorClass), null, options2); Assert.AreEqual(key1, key2); }
/// <summary> /// Returns a type from this scope's type cache, or null if the key cannot be found. /// </summary> /// <param name = "key">The key to be looked up in the cache.</param> /// <returns>The type from this scope's type cache matching the key, or null if the key cannot be found</returns> public Type GetFromCache(CacheKey key) { Type type; typeCache.TryGetValue(key, out type); return type; }
/// <summary> /// Returns a type from this scope's type cache, or null if the key cannot be found. /// </summary> /// <param name="key">The key to be looked up in the cache.</param> /// <returns>The type from this scope's type cache matching the key, or null if the key cannot be found</returns> public Type GetFromCache(CacheKey key) { Type type; if (typeCache.TryGetValue(key, out type)) return type; else return null; }