avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hamm...@apache.org
Subject svn commit: rev 43424 - in avalon/trunk/central/laboratory/avalon-net/DynamicProxy: . Builder Builder/CodeGenerators DynamicProxyTest DynamicProxyTest/ClassInterfaces DynamicProxyTest/Classes
Date Mon, 06 Sep 2004 20:43:17 GMT
Author: hammett
Date: Mon Sep  6 13:43:16 2004
New Revision: 43424

Added:
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMyInterface.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/NoVirtualMethodClass.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SealedMethodsClass.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/ServiceClass.cs   (contents, props changed)
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SpecializedServiceClass.cs   (contents, props changed)
Removed:
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/IMyInterface.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/IMySecondInterface.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/IServiceStatus.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/MyInterfaceImpl.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/MySecondInterfaceImpl.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ServiceStatusImpl.cs
Modified:
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Apache.Avalon.DynamicProxy.csproj
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ProxyGeneratorTestCase.cs
   avalon/trunk/central/laboratory/avalon-net/DynamicProxy/ProxyGenerator.cs
Log:
Supports proxying classes and interfaces now.

Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Apache.Avalon.DynamicProxy.csproj
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Apache.Avalon.DynamicProxy.csproj	(original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Apache.Avalon.DynamicProxy.csproj	Mon Sep  6 13:43:16 2004
@@ -103,6 +103,36 @@
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
+                <File
+                    RelPath = "Builder\IProxyBuilder.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Builder\ProxyBuilderImpl.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Builder\CodeGenerators\BaseCodeGenerator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Builder\CodeGenerators\ClassProxyGenerator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Builder\CodeGenerators\InterfaceProxyGenerator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Builder\CodeGenerators\OpCodesDictionary.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
             </Include>
         </Files>
     </CSHARP>

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,372 @@
+ // Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder.CodeGenerators
+{
+	using System;
+	using System.Collections;
+	using System.Reflection;
+	using System.Reflection.Emit;
+
+	/// <summary>
+	/// Summary description for BaseCodeGenerator.
+	/// </summary>
+	public abstract class BaseCodeGenerator
+	{
+		private TypeBuilder m_typeBuilder;
+		private FieldBuilder m_handlerField;
+		private IList m_generated = new ArrayList();
+
+		protected TypeBuilder MainTypeBuilder
+		{
+			get { return m_typeBuilder; }
+		}
+
+		protected FieldBuilder HandlerFieldBuilder
+		{
+			get { return m_handlerField; }
+		}
+
+		protected virtual ModuleBuilder CreateDynamicModule()
+		{
+			AssemblyName assemblyName = new AssemblyName();
+			assemblyName.Name = "DynamicAssemblyProxyGen";
+
+			AssemblyBuilder assemblyBuilder =
+				AppDomain.CurrentDomain.DefineDynamicAssembly(
+					assemblyName,
+					AssemblyBuilderAccess.Run);
+
+			return assemblyBuilder.DefineDynamicModule(assemblyName.Name, true);
+		}
+
+		protected virtual TypeBuilder CreateTypeBuilder(Type baseType, Type[] interfaces)
+		{
+			ModuleBuilder moduleBuilder = CreateDynamicModule();
+
+			m_typeBuilder = moduleBuilder.DefineType(
+				"ProxyType", TypeAttributes.Public | TypeAttributes.Class, baseType, interfaces);
+
+			m_handlerField = GenerateField();
+			ConstructorBuilder constr = GenerateConstructor();
+
+			return m_typeBuilder;
+		}
+
+		/// <summary>
+		/// Generates a public field holding the <see cref="IInvocationHandler"/>
+		/// </summary>
+		/// <returns><see cref="FieldBuilder"/> instance</returns>
+		protected FieldBuilder GenerateField()
+		{
+			return m_typeBuilder.DefineField("handler",
+			                                 typeof (IInvocationHandler), FieldAttributes.Public);
+		}
+
+		/// <summary>
+		/// Generates one public constructor receiving 
+		/// the <see cref="IInvocationHandler"/> instance.
+		/// </summary>
+		/// <returns><see cref="ConstructorBuilder"/> instance</returns>
+		protected ConstructorBuilder GenerateConstructor()
+		{
+			ConstructorBuilder consBuilder = m_typeBuilder.DefineConstructor(
+				MethodAttributes.Public,
+				CallingConventions.Standard,
+				new Type[] {typeof (IInvocationHandler)});
+
+			ILGenerator ilGenerator = consBuilder.GetILGenerator();
+			ilGenerator.Emit(OpCodes.Ldarg_0);
+			ilGenerator.Emit(OpCodes.Call, typeof (Object).GetConstructor(new Type[0]));
+			ilGenerator.Emit(OpCodes.Ldarg_0);
+			ilGenerator.Emit(OpCodes.Ldarg_1);
+			ilGenerator.Emit(OpCodes.Stfld, m_handlerField);
+			ilGenerator.Emit(OpCodes.Ret);
+
+			return consBuilder;
+		}
+
+		/// <summary>
+		/// 
+		/// </summary>
+		/// <param name="interfaces"></param>
+		protected void GenerateInterfaceImplementation(Type[] interfaces)
+		{
+			foreach(Type inter in interfaces)
+			{
+				GenerateTypeImplementation(inter);
+			}
+		}
+
+		/// <summary>
+		/// Iterates over the interfaces and generate implementation 
+		/// for each method in it.
+		/// </summary>
+		/// <param name="type">Interface type</param>
+		protected void GenerateTypeImplementation(Type type)
+		{
+			if (m_generated.Contains(type))
+			{
+				return;
+			}
+			else
+			{
+				m_generated.Add( type );
+			}
+
+			Type[] baseInterfaces = type.FindInterfaces(new TypeFilter(NoFilterImpl), type);
+
+			GenerateInterfaceImplementation(baseInterfaces);
+			PropertyBuilder[] propertiesBuilder = GenerateProperties(type);
+			GenerateMethods(type, propertiesBuilder);
+		}
+
+		protected virtual PropertyBuilder[] GenerateProperties( Type inter )
+		{
+			PropertyInfo[] properties = inter.GetProperties();
+			PropertyBuilder[] propertiesBuilder = new PropertyBuilder[properties.Length];
+
+			for(int i = 0; i < properties.Length; i++)
+			{
+				propertiesBuilder[i] = GeneratePropertyImplementation(properties[i]);
+			}
+
+			return propertiesBuilder;
+		}
+
+		protected virtual void GenerateMethods( Type inter, PropertyBuilder[] propertiesBuilder )
+		{
+			MethodInfo[] methods = inter.GetMethods();
+
+			foreach(MethodInfo method in methods)
+			{
+				GenerateMethodImplementation(method, propertiesBuilder);
+			}
+		}
+
+		/// <summary>
+		/// Generate property implementation
+		/// </summary>
+		/// <param name="property"></param>
+		protected PropertyBuilder GeneratePropertyImplementation(PropertyInfo property)
+		{
+			return m_typeBuilder.DefineProperty(
+				property.Name, property.Attributes, property.PropertyType, null);
+		}
+
+		/// <summary>
+		/// Generates implementation for each method.
+		/// </summary>
+		/// <param name="method"></param>
+		/// <param name="properties"></param>
+		protected void GenerateMethodImplementation(
+			MethodInfo method, PropertyBuilder[] properties)
+		{
+			if (method.IsFinal)
+			{
+				return;
+			}
+
+			ParameterInfo[] parameterInfo = method.GetParameters();
+
+			Type[] parameters = new Type[parameterInfo.Length];
+
+			for(int i = 0; i < parameterInfo.Length; i++)
+			{
+				parameters[i] = parameterInfo[i].ParameterType;
+			}
+
+			MethodAttributes atts = MethodAttributes.Public | MethodAttributes.Virtual;
+
+			if (method.Name.StartsWith("set_") || method.Name.StartsWith("get_"))
+			{
+				atts = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual;
+			}
+
+			MethodBuilder methodBuilder =
+				m_typeBuilder.DefineMethod(method.Name, atts, CallingConventions.Standard,
+				                           method.ReturnType, parameters);
+
+			if (method.Name.StartsWith("set_") || method.Name.StartsWith("get_"))
+			{
+				foreach(PropertyBuilder property in properties)
+				{
+					if (property == null)
+					{
+						break;
+					}
+
+					if (!property.Name.Equals(method.Name.Substring(4)))
+					{
+						continue;
+					}
+
+					if (methodBuilder.Name.StartsWith("set_"))
+					{
+						property.SetSetMethod(methodBuilder);
+						break;
+					}
+					else
+					{
+						property.SetGetMethod(methodBuilder);
+						break;
+					}
+				}
+			}
+
+			WriteILForMethod(method, methodBuilder, parameters, HandlerFieldBuilder);
+		}
+
+		/// <summary>
+		/// Writes the stack for the method implementation. This 
+		/// method generates the IL stack for property get/set method and
+		/// ordinary methods.
+		/// </summary>
+		/// <remarks>
+		/// The method implementation would be as simple as:
+		/// <code>
+		/// public void SomeMethod( int parameter )
+		/// {
+		///     MethodBase method = MethodBase.GetCurrentMethod();
+		///     handler.Invoke( this, method, new object[] { parameter } );
+		/// }
+		/// </code>
+		/// </remarks>
+		/// <param name="builder"><see cref="MethodBuilder"/> being constructed.</param>
+		/// <param name="parameters"></param>
+		/// <param name="handlerField"></param>
+		protected void WriteILForMethod(MethodInfo method, MethodBuilder builder,
+		                                Type[] parameters, FieldBuilder handlerField)
+		{
+			int arrayPositionInStack = 1;
+
+			ILGenerator ilGenerator = builder.GetILGenerator();
+
+			ilGenerator.DeclareLocal(typeof (MethodBase));
+
+			if (builder.ReturnType != typeof (void))
+			{
+				ilGenerator.DeclareLocal(builder.ReturnType);
+				arrayPositionInStack = 2;
+			}
+
+			ilGenerator.DeclareLocal(typeof (object[]));
+
+			ilGenerator.Emit(OpCodes.Ldtoken, method);
+			ilGenerator.Emit(OpCodes.Call, typeof (MethodBase).GetMethod("GetMethodFromHandle"));
+
+			ilGenerator.Emit(OpCodes.Stloc_0);
+			ilGenerator.Emit(OpCodes.Ldarg_0);
+			ilGenerator.Emit(OpCodes.Ldfld, handlerField);
+			ilGenerator.Emit(OpCodes.Ldarg_0);
+			ilGenerator.Emit(OpCodes.Ldloc_0);
+			ilGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
+			ilGenerator.Emit(OpCodes.Newarr, typeof (object));
+
+			if (parameters.Length != 0)
+			{
+				ilGenerator.Emit(OpCodes.Stloc, arrayPositionInStack);
+				ilGenerator.Emit(OpCodes.Ldloc, arrayPositionInStack);
+			}
+
+			for(int c = 0; c < parameters.Length; c++)
+			{
+				ilGenerator.Emit(OpCodes.Ldc_I4, c);
+				ilGenerator.Emit(OpCodes.Ldarg, c + 1);
+
+				if (parameters[c].IsValueType)
+				{
+					ilGenerator.Emit(OpCodes.Box, parameters[c].UnderlyingSystemType);
+				}
+
+				ilGenerator.Emit(OpCodes.Stelem_Ref);
+				ilGenerator.Emit(OpCodes.Ldloc, arrayPositionInStack);
+			}
+
+			ilGenerator.Emit(OpCodes.Callvirt, typeof (IInvocationHandler).GetMethod("Invoke"));
+
+			if (builder.ReturnType != typeof (void))
+			{
+				if (!builder.ReturnType.IsValueType)
+				{
+					ilGenerator.Emit(OpCodes.Castclass, builder.ReturnType);
+				}
+				else
+				{
+					ilGenerator.Emit(OpCodes.Unbox, builder.ReturnType);
+					ilGenerator.Emit(ConvertTypeToOpCode(builder.ReturnType));
+				}
+
+				ilGenerator.Emit(OpCodes.Stloc, 1);
+
+				Label label = ilGenerator.DefineLabel();
+				ilGenerator.Emit(OpCodes.Br_S, label);
+				ilGenerator.MarkLabel(label);
+				ilGenerator.Emit(OpCodes.Ldloc, 1);
+			}
+			else
+			{
+				ilGenerator.Emit(OpCodes.Pop);
+			}
+
+			ilGenerator.Emit(OpCodes.Ret);
+		}
+
+		/// <summary>
+		/// Converts a Value type to a correspondent OpCode of 
+		/// </summary>
+		/// <param name="type"></param>
+		/// <returns></returns>
+		protected virtual OpCode ConvertTypeToOpCode(Type type)
+		{
+			if (type.IsEnum)
+			{
+				Enum baseType = (Enum) Activator.CreateInstance(type);
+				TypeCode code = baseType.GetTypeCode();
+
+				switch(code)
+				{
+					case TypeCode.Byte:
+						type = typeof (Byte);
+						break;
+					case TypeCode.Int16:
+						type = typeof (Int16);
+						break;
+					case TypeCode.Int32:
+						type = typeof (Int32);
+						break;
+					case TypeCode.Int64:
+						type = typeof (Int64);
+						break;
+				}
+
+				return ConvertTypeToOpCode(type);
+			}
+
+			OpCode opCode = OpCodesDictionary.Instance[ type ];
+
+			if (Object.ReferenceEquals(opCode, OpCodesDictionary.EmptyOpCode))
+			{
+				throw new ArgumentException("Type " + type + " could not be converted to a OpCode");
+			}
+
+			return opCode;
+		}
+
+		public static bool NoFilterImpl(Type type, object criteria)
+		{
+			return true;
+		}
+	}
+}
\ No newline at end of file

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,34 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder.CodeGenerators
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for ClassProxyGenerator.
+	/// </summary>
+	public class ClassProxyGenerator : BaseCodeGenerator
+	{
+		public Type GenerateCode(Type baseClass)
+		{
+			// TODO: interfaces of base class
+			
+			CreateTypeBuilder( baseClass, new Type[0] );
+			GenerateTypeImplementation( baseClass );
+
+			return MainTypeBuilder.CreateType();
+		}
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,37 @@
+ // Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder.CodeGenerators
+{
+	using System;
+	using System.Reflection;
+	using System.Reflection.Emit;
+
+	/// <summary>
+	/// Summary description for InterfaceProxyGenerator.
+	/// </summary>
+	public class InterfaceProxyGenerator : BaseCodeGenerator
+	{
+		public InterfaceProxyGenerator()
+		{
+		}
+
+		public Type GenerateCode(Type[] interfaces)
+		{
+			CreateTypeBuilder( null, interfaces );
+			GenerateInterfaceImplementation( interfaces );
+			return MainTypeBuilder.CreateType();
+		}
+	}
+}
\ No newline at end of file

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,64 @@
+using System.Reflection.Emit;
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder.CodeGenerators
+{
+	using System;
+	using System.Collections;
+
+	/// <summary>
+	/// Summary description for OpCodesDictionary.
+	/// </summary>
+	public sealed class OpCodesDictionary : DictionaryBase
+	{
+		private static readonly OpCodesDictionary m_dict = new OpCodesDictionary();
+
+		private static readonly OpCode m_emptyOpCode = new OpCode();
+
+		private OpCodesDictionary() : base()
+		{
+			Dictionary[ typeof (Int16) ] = OpCodes.Ldind_I2;
+			Dictionary[ typeof (Int32) ] = OpCodes.Ldind_I4;
+			Dictionary[ typeof (Int64) ] = OpCodes.Ldind_I8;
+			Dictionary[ typeof (float) ] = OpCodes.Ldind_R4;
+			Dictionary[ typeof (double) ] = OpCodes.Ldind_R8;
+			Dictionary[ typeof (UInt16) ] = OpCodes.Ldind_U2;
+			Dictionary[ typeof (UInt32) ] = OpCodes.Ldind_U4;
+			Dictionary[ typeof (bool) ] = OpCodes.Ldind_I4;
+		}
+
+		public OpCode this[Type type]
+		{
+			get
+			{
+				if (Dictionary.Contains(type))
+				{
+					return (OpCode) Dictionary[ type ];
+				}
+				return EmptyOpCode;
+			}
+		}
+
+		public static OpCodesDictionary Instance
+		{
+			get { return m_dict; }
+		}
+
+		public static OpCode EmptyOpCode
+		{
+			get { return m_emptyOpCode; }
+		}
+	}
+}
\ No newline at end of file

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,28 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for IProxyBuilder.
+	/// </summary>
+	public interface IProxyBuilder
+	{
+		Type CreateInterfaceProxy( Type[] interfaces );
+
+		Type CreateClassProxy( Type theClass );
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,41 @@
+using Apache.Avalon.DynamicProxy.Builder.CodeGenerators;
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Builder
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for ProxyBuilderImpl.
+	/// </summary>
+	public class ProxyBuilderImpl : IProxyBuilder
+	{
+		#region IProxyBuilder Members
+
+		public Type CreateInterfaceProxy(Type[] interfaces)
+		{
+			InterfaceProxyGenerator generator = new InterfaceProxyGenerator();
+			return generator.GenerateCode( interfaces );
+		}
+
+		public Type CreateClassProxy(Type theClass)
+		{
+			ClassProxyGenerator generator = new ClassProxyGenerator();
+			return generator.GenerateCode( theClass );
+		}
+
+		#endregion
+	}
+}

Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj	(original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj	Mon Sep  6 13:43:16 2004
@@ -99,37 +99,57 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "IMyInterface.cs"
+                    RelPath = "ProxyGeneratorTestCase.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "IMySecondInterface.cs"
+                    RelPath = "Classes\NoVirtualMethodClass.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "IServiceStatus.cs"
+                    RelPath = "Classes\SealedMethodsClass.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "MyInterfaceImpl.cs"
+                    RelPath = "Classes\ServiceClass.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "MySecondInterfaceImpl.cs"
+                    RelPath = "Classes\SpecializedServiceClass.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "ProxyGeneratorTestCase.cs"
+                    RelPath = "ClassInterfaces\IMyInterface.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ClassInterfaces\IMySecondInterface.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ClassInterfaces\IServiceStatus.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ClassInterfaces\MyInterfaceImpl.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "ClassInterfaces\MySecondInterfaceImpl.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "ServiceStatusImpl.cs"
+                    RelPath = "ClassInterfaces\ServiceStatusImpl.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMyInterface.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMyInterface.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,40 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for IMyInterface.
+	/// </summary>
+	public interface IMyInterface
+	{
+		String Name
+		{
+			get;
+			set;
+		}
+
+		bool Started
+		{
+			get;
+			set;
+		}
+
+		int Calc(int x, int y);
+
+		int Calc(int x, int y, int z, Single k);
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,30 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for IMySecondInterface.
+	/// </summary>
+	public interface IMySecondInterface : IMyInterface
+	{
+		String Address
+		{
+			get;
+			set;
+		}
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,45 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Simple enum declaration
+	/// </summary>
+	public enum State
+	{
+		Valid, 
+		Invalid
+	}
+
+	/// <summary>
+	/// Summary description for IServiceStatus.
+	/// </summary>
+	public interface IServiceStatus
+	{
+		int Requests
+		{
+			get;
+		}
+
+		State ActualState
+		{
+			get;
+		}
+
+		void ChangeState(State state);
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,69 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for MyInterfaceImpl.
+	/// </summary>
+	public class MyInterfaceImpl : IMyInterface
+	{
+		private String m_name;
+		private bool m_started;
+
+		public MyInterfaceImpl()
+		{
+		}
+
+		#region IMyInterface Members
+
+		public String Name
+		{
+			get
+			{
+				return m_name;
+			}
+			set
+			{
+				m_name = value;
+			}
+		}
+
+		public bool Started
+		{
+			get
+			{
+				return m_started;
+			}
+			set
+			{
+				m_started = value;
+			}
+		}
+
+		public int Calc(int x, int y)
+		{
+			return x + y;
+		}
+
+		public int Calc(int x, int y, int z, Single k)
+		{
+			return x + y + z + (int)k;
+		}
+
+		#endregion
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,46 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for MySecondInterfaceImpl.
+	/// </summary>
+	public class MySecondInterfaceImpl : MyInterfaceImpl, IMySecondInterface
+	{
+		private String m_address;
+
+		public MySecondInterfaceImpl()
+		{
+		}
+
+		#region IMySecondInterface Members
+
+		public String Address
+		{
+			get
+			{
+				return m_address;
+			}
+			set
+			{
+				m_address = value;
+			}
+		}
+
+		#endregion
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,55 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.ClassInterfaces
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for ServiceStatusImpl.
+	/// </summary>
+	public class ServiceStatusImpl : IServiceStatus
+	{
+		private State m_state = State.Invalid;
+
+		public ServiceStatusImpl()
+		{
+		}
+
+		#region IServiceStatus Members
+
+		public int Requests
+		{
+			get
+			{
+				return 10;
+			}
+		}
+
+		public State ActualState
+		{
+			get
+			{
+				return m_state;
+			}
+		}
+
+		public void ChangeState(State state)
+		{
+			m_state = state;
+		}
+
+		#endregion
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/NoVirtualMethodClass.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/NoVirtualMethodClass.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,29 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.Classes
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for NoVirtualMethodClass.
+	/// </summary>
+	public class NoVirtualMethodClass
+	{
+		public int Sum(int b1, int b2)
+		{
+			return b1 + b2;
+		}
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SealedMethodsClass.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SealedMethodsClass.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,29 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.Classes
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for SealedMethodsClass.
+	/// </summary>
+	public class SealedMethodsClass : ServiceClass
+	{
+		public override sealed int Sum(int b1, int b2)
+		{
+			return b1 + b2;
+		}
+	}
+}

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/ServiceClass.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/ServiceClass.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,74 @@
+ // Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.Classes
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for ServiceClass.
+	/// </summary>
+	public class ServiceClass
+	{
+		public virtual int Sum(int b1, int b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual byte Sum(byte b1, byte b2)
+		{
+			return System.Convert.ToByte( b1 + b2 );
+		}
+
+		public virtual long Sum(long b1, long b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual short Sum(short b1, short b2)
+		{
+			return (short) (b1 + b2);
+		}
+
+		public virtual float Sum(float b1, float b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual double Sum(double b1, double b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual UInt16 Sum(UInt16 b1, UInt16 b2)
+		{
+			return (UInt16) (b1 + b2);
+		}
+
+		public virtual UInt32 Sum(UInt32 b1, UInt32 b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual UInt64 Sum(UInt64 b1, UInt64 b2)
+		{
+			return b1 + b2;
+		}
+
+		public virtual bool Valid
+		{
+			get { return true; }
+		}
+	}
+}
\ No newline at end of file

Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SpecializedServiceClass.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Classes/SpecializedServiceClass.cs	Mon Sep  6 13:43:16 2004
@@ -0,0 +1,29 @@
+// Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy.Test.Classes
+{
+	using System;
+
+	/// <summary>
+	/// Summary description for SpecializedServiceClass.
+	/// </summary>
+	public class SpecializedServiceClass : ServiceClass
+	{
+		public virtual int Subtract(int b1, int b2)
+		{
+			return b1 - b2;
+		}
+	}
+}

Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ProxyGeneratorTestCase.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ProxyGeneratorTestCase.cs	(original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/ProxyGeneratorTestCase.cs	Mon Sep  6 13:43:16 2004
@@ -20,6 +20,8 @@
 	using NUnit.Framework;
 
 	using Apache.Avalon.DynamicProxy;
+	using Apache.Avalon.DynamicProxy.Test.Classes;
+	using Apache.Avalon.DynamicProxy.Test.ClassInterfaces;
 
 	/// <summary>
 	/// Summary description for ProxyGeneratorTestCase.
@@ -28,6 +30,100 @@
 	public class ProxyGeneratorTestCase : Assertion
 	{
 		[Test]
+		public void ProxyForClass()
+		{
+			object proxy = ProxyGenerator.CreateClassProxy( 
+				typeof(ServiceClass), new ResultModifiedInvocationHandler( new ServiceClass() ) );
+			
+			AssertNotNull( proxy );
+			Assert( typeof(ServiceClass).IsAssignableFrom( proxy.GetType() ) );
+
+			ServiceClass inter = (ServiceClass) proxy;
+
+			AssertEquals( 44, inter.Sum( 20, 25 ) );
+			AssertEquals( true, inter.Valid );
+		}
+
+		[Test]
+		public void ProxyForClassWithSuperClass()
+		{
+			object proxy = ProxyGenerator.CreateClassProxy( 
+				typeof(SpecializedServiceClass), new ResultModifiedInvocationHandler( new SpecializedServiceClass() ) );
+			
+			AssertNotNull( proxy );
+			Assert( typeof(ServiceClass).IsAssignableFrom( proxy.GetType() ) );
+			Assert( typeof(SpecializedServiceClass).IsAssignableFrom( proxy.GetType() ) );
+
+			SpecializedServiceClass inter = (SpecializedServiceClass) proxy;
+
+			AssertEquals( 44, inter.Sum( 20, 25 ) );
+			AssertEquals( -6, inter.Subtract( 20, 25 ) );
+			AssertEquals( true, inter.Valid );
+		}
+
+		[Test]
+		public void ProxyingClassWithoutVirtualMethods()
+		{
+			object proxy = ProxyGenerator.CreateClassProxy( 
+				typeof(NoVirtualMethodClass), new ResultModifiedInvocationHandler( new SpecializedServiceClass() ) );
+			
+			AssertNotNull( proxy );
+			Assert( typeof(NoVirtualMethodClass).IsAssignableFrom( proxy.GetType() ) );
+
+			NoVirtualMethodClass inter = (NoVirtualMethodClass) proxy;
+
+			AssertEquals( 45, inter.Sum( 20, 25 ) );
+		}
+
+		[Test]
+		public void ProxyingClassWithSealedMethods()
+		{
+			object proxy = ProxyGenerator.CreateClassProxy( 
+				typeof(SealedMethodsClass), new ResultModifiedInvocationHandler( new SpecializedServiceClass() ) );
+			
+			AssertNotNull( proxy );
+			Assert( typeof(SealedMethodsClass).IsAssignableFrom( proxy.GetType() ) );
+
+			SealedMethodsClass inter = (SealedMethodsClass) proxy;
+
+			AssertEquals( 45, inter.Sum( 20, 25 ) );
+		}
+
+		[Test]
+		public void CreateClassProxyInvalidArguments()
+		{
+			try
+			{
+				ProxyGenerator.CreateClassProxy( 
+					typeof(ICloneable), new StandardInvocationHandler( new SpecializedServiceClass() ) );
+			}
+			catch(ArgumentException)
+			{
+				// Expected
+			}
+
+			try
+			{
+				ProxyGenerator.CreateClassProxy( 
+					null, new StandardInvocationHandler( new SpecializedServiceClass() ) );
+			}
+			catch(ArgumentNullException)
+			{
+				// Expected
+			}
+
+			try
+			{
+				ProxyGenerator.CreateClassProxy( 
+					typeof(SpecializedServiceClass), null );
+			}
+			catch(ArgumentNullException)
+			{
+				// Expected
+			}
+		}
+
+		[Test]
 		public void TestGenerationSimpleInterface()
 		{
 			object proxy = ProxyGenerator.CreateProxy( 
@@ -98,6 +194,22 @@
 
 			#endregion
 		}
+	}
+
+	public class ResultModifiedInvocationHandler : StandardInvocationHandler
+	{
+		public ResultModifiedInvocationHandler( object instanceDelegate ) : base(instanceDelegate)
+		{
+		}
+
+		protected override void PostInvoke(object proxy, System.Reflection.MethodInfo method, ref object returnValue, params object[] arguments)
+		{
+			if ( returnValue != null && returnValue.GetType() == typeof(int))
+			{
+				int value = (int) returnValue;
+				returnValue = --value;
+			}
+		}
 	}
 }
 

Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/ProxyGenerator.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/ProxyGenerator.cs	(original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/ProxyGenerator.cs	Mon Sep  6 13:43:16 2004
@@ -1,437 +1,116 @@
-// Copyright 2004 The Apache Software Foundation
-// 
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// 
-//     http://www.apache.org/licenses/LICENSE-2.0
-// 
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-namespace Apache.Avalon.DynamicProxy
-{
-	using System;
-	using System.Reflection;
-	using System.Reflection.Emit;
-
-	/// <summary>
-	/// Generates a Java style proxy. This overrides the .Net proxy requirements 
-	/// that forces one to extend MarshalByRefObject or (for a different purpose)
-	/// ContextBoundObject to have a Proxiable class.
-	/// </summary>
-	/// <remarks>
-	/// The <see cref="ProxyGenerator"/> should be used to generate a class 
-	/// implementing the specified interfaces. The class implementation will 
-	/// only call the internal <see cref="IInvocationHandler"/> instance.
-	/// </remarks>
-	/// <remarks>
-	/// This proxy implementation currently doesn't not supports ref and out arguments 
-	/// in methods.
-	/// </remarks>
-	/// <example>
-	/// <code>
-	/// MyInvocationHandler handler = ...
-	/// IInterfaceExposed proxy = 
-	///		ProxyGenerator.CreateProxy( new Type[] { typeof(IInterfaceExposed) }, handler );
-	/// </code>
-	/// </example>
-	public class ProxyGenerator
-	{
-		/// <summary>
-		/// Private construtor
-		/// </summary>
-		private ProxyGenerator()
-		{
-		}
-
-		/// <summary>
-		/// Generates a proxy implementing all the specified interfaces and
-		/// redirecting method invocations to the specifed handler.
-		/// </summary>
-		/// <param name="theInterface">Interface to be implemented</param>
-		/// <param name="handler">instance of <see cref="IInvocationHandler"/></param>
-		/// <returns>Proxy instance</returns>
-		public static object CreateProxy(Type theInterface, IInvocationHandler handler)
-		{
-			return CreateProxy(new Type[] { theInterface }, handler );
-		}
-
-		/// <summary>
-		/// Generates a proxy implementing all the specified interfaces and
-		/// redirecting method invocations to the specifed handler.
-		/// </summary>
-		/// <param name="interfaces">Array of interfaces to be implemented</param>
-		/// <param name="handler">instance of <see cref="IInvocationHandler"/></param>
-		/// <returns>Proxy instance</returns>
-		public static object CreateProxy(Type[] interfaces, IInvocationHandler handler)
-		{
-			if (interfaces == null)
-			{
-				throw new ArgumentNullException("interfaces");
-			}
-			if (handler == null)
-			{
-				throw new ArgumentNullException("handler");
-			}
-			if (interfaces.Length == 0)
-			{
-				throw new ArgumentException("Can't handle an empty interface array");
-			}
-
-			AssemblyName assemblyName = new AssemblyName();
-			assemblyName.Name = "DynamicAssemblyProxyGen";
-
-			AssemblyBuilder assemblyBuilder = 
-				AppDomain.CurrentDomain.DefineDynamicAssembly(
-				assemblyName, 
-				AssemblyBuilderAccess.Run);
-			
-			ModuleBuilder moduleBuilder = 
-				assemblyBuilder.DefineDynamicModule( assemblyName.Name, true );
-
-			TypeBuilder typeBuilder = moduleBuilder.DefineType( 
-				"ProxyType", TypeAttributes.Public|TypeAttributes.Class, null, interfaces);
-
-			FieldBuilder handlerField = GenerateField( typeBuilder );
-			ConstructorBuilder constr = GenerateConstructor( typeBuilder, handlerField );
-
-			GenerateInterfaceImplementation( typeBuilder, interfaces, handlerField );
-
-			Type generatedType = typeBuilder.CreateType();
-
-			return Activator.CreateInstance( generatedType, new object[] { handler } );
-		}
-
-		/// <summary>
-		/// 
-		/// </summary>
-		/// <param name="typeBuilder"></param>
-		/// <param name="interfaces"></param>
-		private static void GenerateInterfaceImplementation( TypeBuilder typeBuilder, 
-			Type[] interfaces, FieldBuilder handlerField )
-		{
-			foreach(Type inter in interfaces)
-			{
-				GenerateInterfaceImplementation( typeBuilder, inter, handlerField );
-			}
-		}
-
-		/// <summary>
-		/// Iterates over the interfaces and generate implementation 
-		/// for each method in it.
-		/// </summary>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <param name="inter">Interface type</param>
-		private static void GenerateInterfaceImplementation( TypeBuilder typeBuilder, 
-			Type inter, FieldBuilder handlerField )
-		{
-			if (!inter.IsInterface)
-			{
-				throw new ArgumentException("Type array expects interfaces only.");
-			}
-
-			Type[] baseInterfaces = inter.FindInterfaces( new TypeFilter( NoFilterImpl ), inter );
-
-			GenerateInterfaceImplementation( typeBuilder, baseInterfaces, handlerField );
-
-			PropertyInfo[] properties = inter.GetProperties();
-			PropertyBuilder[] propertiesBuilder = new PropertyBuilder[properties.Length];
-
-			for(int i=0; i < properties.Length; i++)
-			{
-				GeneratePropertyImplementation( typeBuilder, properties[i], ref propertiesBuilder[i] );
-			}
-
-			MethodInfo[] methods = inter.GetMethods();
-
-			foreach(MethodInfo method in methods)
-			{
-				GenerateMethodImplementation( typeBuilder, method, 
-					propertiesBuilder, handlerField, inter );
-			}
-		}
-
-		/// <summary>
-		/// Generates a public field holding the <see cref="IInvocationHandler"/>
-		/// </summary>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <returns><see cref="FieldBuilder"/> instance</returns>
-		private static FieldBuilder GenerateField( TypeBuilder typeBuilder )
-		{
-			return typeBuilder.DefineField( "handler", 
-				typeof(IInvocationHandler), FieldAttributes.Public );
-		}
-
-		/// <summary>
-		/// Generates one public constructor receiving 
-		/// the <see cref="IInvocationHandler"/> instance.
-		/// </summary>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <param name="handlerField"><see cref="FieldBuilder"/> instance representing the handler field</param>
-		/// <returns><see cref="ConstructorBuilder"/> instance</returns>
-		private static ConstructorBuilder GenerateConstructor( 
-			TypeBuilder typeBuilder, FieldBuilder handlerField )
-		{
-			ConstructorBuilder consBuilder = typeBuilder.DefineConstructor(
-				MethodAttributes.Public, 
-				CallingConventions.Standard, 
-				new Type[] { typeof(IInvocationHandler) } );
-			
-			ILGenerator ilGenerator = consBuilder.GetILGenerator();
-			ilGenerator.Emit(OpCodes.Ldarg_0);
-			ilGenerator.Emit(OpCodes.Call, typeof(Object).GetConstructor(new Type[0]));
-			ilGenerator.Emit(OpCodes.Ldarg_0);
-			ilGenerator.Emit(OpCodes.Ldarg_1);
-			ilGenerator.Emit(OpCodes.Stfld, handlerField);
-			ilGenerator.Emit(OpCodes.Ret);
-
-			return consBuilder;
-		}
-
-		/// <summary>
-		/// Generate property implementation
-		/// </summary>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <param name="property"></param>
-		/// <param name="propertyBuilder"></param>
-		private static void GeneratePropertyImplementation( 
-			TypeBuilder typeBuilder, PropertyInfo property, ref PropertyBuilder propertyBuilder )
-		{
-			propertyBuilder = typeBuilder.DefineProperty( 
-				property.Name, property.Attributes, property.PropertyType, null);
-		}
-
-		/// <summary>
-		/// Generates implementation for each method.
-		/// </summary>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <param name="method"></param>
-		/// <param name="properties"></param>
-		private static void GenerateMethodImplementation( 
-			TypeBuilder typeBuilder, MethodInfo method, 
-			PropertyBuilder[] properties, FieldBuilder handlerField, Type inter )
-		{
-			ParameterInfo[] parameterInfo = method.GetParameters();
-
-			System.Type[] parameters = new System.Type[parameterInfo.Length];
-			
-			for (int i=0; i<parameterInfo.Length; i++)
-			{
-				parameters[i] = parameterInfo[i].ParameterType;
-			}
-
-			MethodAttributes atts = MethodAttributes.Public|MethodAttributes.Virtual;
-
-			if ( method.Name.StartsWith("set_") || method.Name.StartsWith("get_") )
-			{
-				atts = MethodAttributes.Public|MethodAttributes.SpecialName|MethodAttributes.Virtual;
-			}
-
-			MethodBuilder methodBuilder = 
-				typeBuilder.DefineMethod( method.Name, atts, CallingConventions.Standard, 
-				method.ReturnType, parameters );
-
-			if ( method.Name.StartsWith("set_") || method.Name.StartsWith("get_") )
-			{
-				foreach( PropertyBuilder property in properties )
-				{
-					if (property == null)
-					{
-						break;
-					}
-
-					if (!property.Name.Equals( method.Name.Substring(4) ))
-					{
-						continue;
-					}
-
-					if ( methodBuilder.Name.StartsWith("set_") )
-					{
-						property.SetSetMethod( methodBuilder );
-						break;
-					}
-					else 
-					{
-						property.SetGetMethod( methodBuilder );
-						break;
-					}
-				}
-			}
-
-			WriteILForMethod( method, methodBuilder, parameters, handlerField );
-		}
-
-		/// <summary>
-		/// Writes the stack for the method implementation. This 
-		/// method generates the IL stack for property get/set method and
-		/// ordinary methods.
-		/// </summary>
-		/// <remarks>
-		/// The method implementation would be as simple as:
-		/// <code>
-		/// public void SomeMethod( int parameter )
-		/// {
-		///     MethodBase method = MethodBase.GetCurrentMethod();
-		///     handler.Invoke( this, method, new object[] { parameter } );
-		/// }
-		/// </code>
-		/// </remarks>
-		/// <param name="typeBuilder"><see cref="TypeBuilder"/> being constructed.</param>
-		/// <param name="parameters"></param>
-		/// <param name="handlerField"></param>
-		private static void WriteILForMethod( MethodInfo method, MethodBuilder builder, 
-			System.Type[] parameters, FieldBuilder handlerField )
-		{
-			int arrayPositionInStack = 1;
-
-			ILGenerator ilGenerator = builder.GetILGenerator();
-
-			ilGenerator.DeclareLocal( typeof( MethodBase ) );
-
-			if (builder.ReturnType != typeof(void))
-			{
-				ilGenerator.DeclareLocal(builder.ReturnType);
-				arrayPositionInStack = 2;
-			}
-
-			ilGenerator.DeclareLocal( typeof(object[]) );
-
-			ilGenerator.Emit(OpCodes.Ldtoken, method);
-			ilGenerator.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle"));
-
-			ilGenerator.Emit(OpCodes.Stloc_0);
-			ilGenerator.Emit(OpCodes.Ldarg_0);
-			ilGenerator.Emit(OpCodes.Ldfld, handlerField);
-			ilGenerator.Emit(OpCodes.Ldarg_0);
-			ilGenerator.Emit(OpCodes.Ldloc_0);
-			ilGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
-			ilGenerator.Emit(OpCodes.Newarr, typeof(object) );
-
-			if (parameters.Length != 0)
-			{
-				ilGenerator.Emit(OpCodes.Stloc, arrayPositionInStack);
-				ilGenerator.Emit(OpCodes.Ldloc, arrayPositionInStack);
-			}
-
-			for (int c=0; c<parameters.Length; c++)
-			{
-				ilGenerator.Emit(OpCodes.Ldc_I4, c);
-				ilGenerator.Emit(OpCodes.Ldarg, c+1);
-
-				if (parameters[c].IsValueType)
-				{
-					ilGenerator.Emit(OpCodes.Box, parameters[c].UnderlyingSystemType);
-				}
-
-				ilGenerator.Emit(OpCodes.Stelem_Ref);
-				ilGenerator.Emit(OpCodes.Ldloc, arrayPositionInStack);
-			}
-
-			ilGenerator.Emit(OpCodes.Callvirt, typeof(IInvocationHandler).GetMethod("Invoke") );
-
-			if (builder.ReturnType != typeof(void))
-			{
-				if (!builder.ReturnType.IsValueType)
-				{
-					ilGenerator.Emit(OpCodes.Castclass, builder.ReturnType);
-				}
-				else
-				{
-					ilGenerator.Emit(OpCodes.Unbox, builder.ReturnType);
-					ilGenerator.Emit(ConvertTypeToOpCode(builder.ReturnType));
-				}
-
-				ilGenerator.Emit(OpCodes.Stloc, 1);
-
-				Label label = ilGenerator.DefineLabel();
-				ilGenerator.Emit(OpCodes.Br_S, label);
-				ilGenerator.MarkLabel(label);
-				ilGenerator.Emit(OpCodes.Ldloc, 1);
-			}
-			else
-			{
-				ilGenerator.Emit(OpCodes.Pop);
-			}
-
-			ilGenerator.Emit(OpCodes.Ret);
-		}
-
-		/// <summary>
-		/// Converts a Value type to a correspondent OpCode of 
-		/// </summary>
-		/// <param name="type"></param>
-		/// <returns></returns>
-		private static OpCode ConvertTypeToOpCode( Type type )
-		{
-			if (type.IsEnum)
-			{
-				System.Enum baseType = (System.Enum) Activator.CreateInstance( type );
-				TypeCode code = baseType.GetTypeCode();
-				
-				switch(code)
-				{
-					case TypeCode.Byte:
-						type = typeof(Byte);
-						break;
-					case TypeCode.Int16:
-						type = typeof(Int16);
-						break;
-					case TypeCode.Int32:
-						type = typeof(Int32);
-						break;
-					case TypeCode.Int64:
-						type = typeof(Int64);
-						break;
-				}
-
-				return ConvertTypeToOpCode( type );
-			}
-
-			if ( type.Equals( typeof(Int32) ) )
-			{
-				return OpCodes.Ldind_I4;
-			}
-			else if ( type.Equals( typeof(Int16) ) )
-			{
-				return OpCodes.Ldind_I2;
-			}
-			else if ( type.Equals( typeof(Int64) ) )
-			{
-				return OpCodes.Ldind_I8;
-			}
-			else if ( type.Equals( typeof(Single) ) )
-			{
-				return OpCodes.Ldind_R4;
-			}
-			else if ( type.Equals( typeof(Double) ) )
-			{
-				return OpCodes.Ldind_R8;
-			}
-			else if ( type.Equals( typeof(UInt16) ) )
-			{
-				return OpCodes.Ldind_U2;
-			}
-			else if ( type.Equals( typeof(UInt32) ) )
-			{
-				return OpCodes.Ldind_U4;
-			}
-			else if ( type.Equals( typeof(Boolean) ) )
-			{
-				return OpCodes.Ldind_I4;
-			}
-			else
-			{
-				throw new ArgumentException("Type " + type + " could not be converted to a OpCode");
-			}
-		}
-
-		public static bool NoFilterImpl( Type type, object criteria )
-		{
-			return true;
-		}
-	}
-}
+ // Copyright 2004 The Apache Software Foundation
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Apache.Avalon.DynamicProxy
+{
+	using System;
+	using System.Reflection;
+	using System.Reflection.Emit;
+
+	using Apache.Avalon.DynamicProxy.Builder;
+
+	/// <summary>
+	/// Generates a Java style proxy. This overrides the .Net proxy requirements 
+	/// that forces one to extend MarshalByRefObject or (for a different purpose)
+	/// ContextBoundObject to have a Proxiable class.
+	/// </summary>
+	/// <remarks>
+	/// The <see cref="ProxyGenerator"/> should be used to generate a class 
+	/// implementing the specified interfaces. The class implementation will 
+	/// only call the internal <see cref="IInvocationHandler"/> instance.
+	/// </remarks>
+	/// <remarks>
+	/// This proxy implementation currently doesn't not supports ref and out arguments 
+	/// in methods.
+	/// </remarks>
+	/// <example>
+	/// <code>
+	/// MyInvocationHandler handler = ...
+	/// IInterfaceExposed proxy = 
+	///		ProxyGenerator.CreateProxy( new Type[] { typeof(IInterfaceExposed) }, handler );
+	/// </code>
+	/// </example>
+	public abstract class ProxyGenerator
+	{
+		private static IProxyBuilder m_builder = new ProxyBuilderImpl();
+
+		public static IProxyBuilder ProxyBuilder
+		{
+			get { return m_builder; }
+			set { m_builder = value; }
+		}
+
+		public static object CreateClassProxy(Type baseClass, IInvocationHandler handler)
+		{
+			if (baseClass == null)
+			{
+				throw new ArgumentNullException("theClass");
+			}
+			if (baseClass.IsInterface)
+			{
+				throw new ArgumentException("'baseClass' must be a class, not an interface");
+			}
+			if (handler == null)
+			{
+				throw new ArgumentNullException("handler");
+			}
+
+			Type newType = ProxyBuilder.CreateClassProxy(baseClass);
+			return CreateProxyInstance( newType, handler );
+		}
+
+		/// <summary>
+		/// Generates a proxy implementing all the specified interfaces and
+		/// redirecting method invocations to the specifed handler.
+		/// </summary>
+		/// <param name="theInterface">Interface to be implemented</param>
+		/// <param name="handler">instance of <see cref="IInvocationHandler"/></param>
+		/// <returns>Proxy instance</returns>
+		public static object CreateProxy(Type theInterface, IInvocationHandler handler)
+		{
+			return CreateProxy(new Type[] {theInterface}, handler);
+		}
+
+		/// <summary>
+		/// Generates a proxy implementing all the specified interfaces and
+		/// redirecting method invocations to the specifed handler.
+		/// </summary>
+		/// <param name="interfaces">Array of interfaces to be implemented</param>
+		/// <param name="handler">instance of <see cref="IInvocationHandler"/></param>
+		/// <returns>Proxy instance</returns>
+		public static object CreateProxy(Type[] interfaces, IInvocationHandler handler)
+		{
+			if (interfaces == null)
+			{
+				throw new ArgumentNullException("interfaces");
+			}
+			if (handler == null)
+			{
+				throw new ArgumentNullException("handler");
+			}
+			if (interfaces.Length == 0)
+			{
+				throw new ArgumentException("Can't handle an empty interface array");
+			}
+
+			Type newType = ProxyBuilder.CreateInterfaceProxy(interfaces);
+			return CreateProxyInstance( newType, handler );
+		}
+
+		private static object CreateProxyInstance(Type type, IInvocationHandler handler)
+		{
+			return Activator.CreateInstance(type, new object[] {handler});
+		}
+	}
+}
\ No newline at end of file

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org


Mime
View raw message