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;
        }
Beispiel #2
0
		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;
		}
Beispiel #4
0
		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);
		}
Beispiel #5
0
		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;
		}
Beispiel #8
0
		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);
		}
Beispiel #9
0
		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);
		}
Beispiel #14
0
		/// <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];
		}
Beispiel #15
0
		/// <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;
		}
Beispiel #16
0
		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);
		}
Beispiel #22
0
		/// <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);
		}
Beispiel #25
0
		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);
		}
Beispiel #26
0
		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);
		}
Beispiel #27
0
		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);
		}
Beispiel #28
0
		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);
		}
Beispiel #29
0
		/// <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;
		}
Beispiel #30
0
		/// <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;
		}