Author: hammett Date: Tue Sep 28 19:27:47 2004 New Revision: 47443 Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Apache.Avalon.DynamicProxy.csproj (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/AssemblyInfo.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ModuleScope.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/DefaultProxyBuilder.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/GeneratorContext.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/IProxyBuilder.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/DynamicProxy.sln (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/IInvocationHandler.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/ProxyGenerator.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/StandardInvocationHandler.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/AssemblyInfo.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CachedTypeTestCase.cs avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IMyInterface.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/MySerializableClass.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/NoVirtualMethodClass.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/SealedMethodsClass.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/ServiceClass.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/SpecializedServiceClass.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CustomProxyGeneratorTestCase.cs (contents, props changed) avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ProxyGeneratorTestCase.cs avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/SerializableClassTestCase.cs (contents, props changed) Log: Reorganizing directories.
Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Apache.Avalon.DynamicProxy.csproj ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Apache.Avalon.DynamicProxy.csproj Tue Sep 28 19:27:47 2004 @@ -0,0 +1,150 @@ +<VisualStudioProject> + <CSHARP + ProjectType = "Local" + ProductVersion = "7.10.3077" + SchemaVersion = "2.0" + ProjectGuid = "{70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}" + > + <Build> + <Settings + ApplicationIcon = "" + AssemblyKeyContainerName = "" + AssemblyName = "Apache.Avalon.DynamicProxy" + AssemblyOriginatorKeyFile = "" + DefaultClientScript = "JScript" + DefaultHTMLPageLayout = "Grid" + DefaultTargetSchema = "IE50" + DelaySign = "false" + OutputType = "Library" + PreBuildEvent = "" + PostBuildEvent = "" + RootNamespace = "Apache.Avalon.DynamicProxy" + RunPostBuildEvent = "OnBuildSuccess" + StartupObject = "" + > + <Config + Name = "Debug" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "DEBUG;TRACE" + DocumentationFile = "" + DebugSymbols = "true" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "false" + OutputPath = "..\bin\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + <Config + Name = "Release" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "TRACE" + DocumentationFile = "" + DebugSymbols = "false" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "true" + OutputPath = "..\..\bin\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + </Settings> + <References> + <Reference + Name = "System" + AssemblyName = "System" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" + /> + <Reference + Name = "System.Data" + AssemblyName = "System.Data" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" + /> + <Reference + Name = "System.XML" + AssemblyName = "System.Xml" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" + /> + </References> + </Build> + <Files> + <Include> + <File + RelPath = "AssemblyInfo.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "IInvocationHandler.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "ProxyGenerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "StandardInvocationHandler.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Builder\DefaultProxyBuilder.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Builder\GeneratorContext.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Builder\IProxyBuilder.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\ModuleScope.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Builder\CodeGenerators\OpCodesDictionary.cs" + SubType = "Code" + BuildAction = "Compile" + /> + </Include> + </Files> + </CSHARP> +</VisualStudioProject> + Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/AssemblyInfo.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/AssemblyInfo.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,32 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Avalon DynamicProxy")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Avalon DynamicProxy")] +[assembly: AssemblyCopyright("Copyright (c) 2004 The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("1.0.0.1")] + +#if STRONG +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("../../../../ApacheAvalon.snk")] +[assembly: AssemblyKeyName("")] +#endif Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,472 @@ +using System.Text; +// 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 Type m_baseType = typeof (Object); + private TypeBuilder m_typeBuilder; + private FieldBuilder m_handlerField; + private ConstructorBuilder m_constBuilder; + private IList m_generated = new ArrayList(); + + private GeneratorContext m_context; + private ModuleScope m_moduleScope; + + protected BaseCodeGenerator(ModuleScope moduleScope) : this(moduleScope, new GeneratorContext()) + { + } + + protected BaseCodeGenerator(ModuleScope moduleScope, GeneratorContext context) + { + m_moduleScope = moduleScope; + m_context = context; + } + + protected ModuleScope ModuleScope + { + get { return m_moduleScope; } + } + + protected GeneratorContext Context + { + get { return m_context; } + } + + protected TypeBuilder MainTypeBuilder + { + get { return m_typeBuilder; } + } + + protected FieldBuilder HandlerFieldBuilder + { + get { return m_handlerField; } + } + + protected ConstructorBuilder DefaultConstructorBuilder + { + get { return m_constBuilder; } + } + + protected Type GetFromCache( Type baseClass, Type[] interfaces ) + { + return ModuleScope[ GenerateTypeName( baseClass, interfaces ) ] as Type; + } + + protected void RegisterInCache( Type generatedType ) + { + ModuleScope[ generatedType.Name ] = generatedType; + } + + protected virtual TypeBuilder CreateTypeBuilder(Type baseType, Type[] interfaces) + { + String typeName = GenerateTypeName(baseType, interfaces); + + ModuleBuilder moduleBuilder = ModuleScope.ObtainDynamicModule(); + + TypeAttributes flags = TypeAttributes.Public | TypeAttributes.Class; + + if (baseType != typeof(Object)) + { + if (baseType.IsSerializable) + { + flags |= TypeAttributes.Serializable; + } + } + + m_baseType = baseType; + m_typeBuilder = moduleBuilder.DefineType( + typeName, flags, baseType, interfaces); + + m_handlerField = GenerateField(); + m_constBuilder = GenerateConstructor(); + + return m_typeBuilder; + } + + protected virtual String GenerateTypeName(Type type, Type[] interfaces) + { + StringBuilder sb = new StringBuilder(); + foreach(Type inter in interfaces) + { + sb.Append('_'); + sb.Append(inter.Name); + } + /// Naive implementation + return String.Format("ProxyType{0}{1}", type.Name, sb.ToString()); + } + + protected virtual void EnhanceType() + { + if (Context.EnhanceType != null) + { + Context.EnhanceType(MainTypeBuilder, HandlerFieldBuilder, DefaultConstructorBuilder); + } + } + + protected virtual Type[] ScreenInterfaces(Type[] interfaces) + { + if (Context.ScreenInterfaces != null) + { + interfaces = Context.ScreenInterfaces(interfaces); + } + + return interfaces; + } + + protected virtual Type CreateType() + { + Type newType = MainTypeBuilder.CreateType(); + + RegisterInCache( newType ); + + return newType; + } + + /// <summary> + /// Generates a public field holding the <see cref="IInvocationHandler"/> + /// </summary> + /// <returns><see cref="FieldBuilder"/> instance</returns> + protected FieldBuilder GenerateField() + { + return GenerateField("handler", typeof (IInvocationHandler)); + } + + /// <summary> + /// Generates a public field + /// </summary> + /// <param name="name">Field's name</param> + /// <param name="type">Field's type</param> + /// <returns></returns> + protected FieldBuilder GenerateField(String name, Type type) + { + return m_typeBuilder.DefineField(name, + 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, m_baseType.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) + { + if (!Context.ShouldSkip(inter)) + { + GenerateTypeImplementation(inter, false); + } + } + } + + /// <summary> + /// Iterates over the interfaces and generate implementation + /// for each method in it. + /// </summary> + /// <param name="type">Type class</param> + /// <param name="ignoreInterfaces">Interface type</param> + protected void GenerateTypeImplementation(Type type, bool ignoreInterfaces) + { + if (m_generated.Contains(type)) + { + return; + } + else + { + m_generated.Add(type); + } + + if (!ignoreInterfaces) + { + 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/src/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,52 @@ +// 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 ClassProxyGenerator(ModuleScope scope) : base(scope) + { + } + + public ClassProxyGenerator(ModuleScope scope, GeneratorContext context) : base(scope, context) + { + } + + public Type GenerateCode(Type baseClass) + { + Type[] interfaces = new Type[0]; + interfaces = ScreenInterfaces(interfaces); + + Type cacheType = GetFromCache(baseClass, interfaces); + + if (cacheType != null) + { + return cacheType; + } + + CreateTypeBuilder( baseClass, interfaces ); + GenerateTypeImplementation( baseClass, true ); + + EnhanceType(); + + return CreateType(); + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,52 @@ + // 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 InterfaceProxyGenerator. + /// </summary> + public class InterfaceProxyGenerator : BaseCodeGenerator + { + public InterfaceProxyGenerator(ModuleScope scope) : base(scope) + { + } + + public InterfaceProxyGenerator(ModuleScope scope, GeneratorContext context) : base(scope, context) + { + } + + public virtual Type GenerateCode(Type[] interfaces) + { + interfaces = ScreenInterfaces(interfaces); + + Type cacheType = GetFromCache(typeof(Object), interfaces); + + if (cacheType != null) + { + return cacheType; + } + + CreateTypeBuilder( typeof(Object), interfaces ); + GenerateInterfaceImplementation( interfaces ); + + EnhanceType(); + + return CreateType(); + } + + } +} \ No newline at end of file Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ModuleScope.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/ModuleScope.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,80 @@ +// 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; + using System.Collections; + + /// <summary> + /// Summary description for ModuleScope. + /// </summary> + public class ModuleScope + { + private static readonly String FILE_NAME = "GeneratedAssembly.dll"; + + /// <summary> + /// Avoid leaks caused by non disposal of generated types. + /// </summary> + private ModuleBuilder m_moduleBuilder = null; + + /// <summary> + /// Keep track of generated types + /// </summary> + private Hashtable m_typeCache = Hashtable.Synchronized(new Hashtable()); + + /// <summary> + /// Used to lock the module builder creation + /// </summary> + private object m_lockobj = new object(); + + private AssemblyBuilder m_assemblyBuilder; + + public ModuleBuilder ObtainDynamicModule() + { + lock (m_lockobj) + { + if (m_moduleBuilder == null) + { + AssemblyName assemblyName = new AssemblyName(); + assemblyName.Name = "DynamicAssemblyProxyGen"; + +#if ( DEBUG ) + m_assemblyBuilder = + AppDomain.CurrentDomain.DefineDynamicAssembly( + assemblyName, + AssemblyBuilderAccess.RunAndSave); + m_moduleBuilder = m_assemblyBuilder.DefineDynamicModule(assemblyName.Name, FILE_NAME); +#else + m_assemblyBuilder = + AppDomain.CurrentDomain.DefineDynamicAssembly( + assemblyName, + AssemblyBuilderAccess.Run); + m_moduleBuilder = m_assemblyBuilder.DefineDynamicModule(assemblyName.Name, true); +#endif + } + } + + return m_moduleBuilder; + } + + public Type this[String name] + { + get { return m_typeCache[name] as Type; } + set { m_typeCache[name] = value; } + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/CodeGenerators/OpCodesDictionary.cs Tue Sep 28 19:27:47 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/src/DynamicProxy/Builder/DefaultProxyBuilder.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/DefaultProxyBuilder.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,60 @@ +// 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; + using Apache.Avalon.DynamicProxy.Builder.CodeGenerators; + + /// <summary> + /// Summary description for DefaultProxyBuilder. + /// </summary> + public class DefaultProxyBuilder : IProxyBuilder + { + ModuleScope m_scope = new ModuleScope(); + + public DefaultProxyBuilder() + { + + } + + #region IProxyBuilder Members + + public virtual Type CreateInterfaceProxy(Type[] interfaces) + { + InterfaceProxyGenerator generator = new InterfaceProxyGenerator(m_scope); + return generator.GenerateCode( interfaces ); + } + + public virtual Type CreateClassProxy(Type theClass) + { + ClassProxyGenerator generator = new ClassProxyGenerator(m_scope); + return generator.GenerateCode( theClass ); + } + + public virtual Type CreateCustomInterfaceProxy(Type[] interfaces, GeneratorContext context) + { + InterfaceProxyGenerator generator = new InterfaceProxyGenerator(m_scope, context); + return generator.GenerateCode( interfaces ); + } + + public virtual Type CreateCustomClassProxy(Type theClass, GeneratorContext context) + { + ClassProxyGenerator generator = new ClassProxyGenerator(m_scope, context); + return generator.GenerateCode( theClass ); + } + + #endregion + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/GeneratorContext.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/GeneratorContext.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,68 @@ +// 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.Collections; + + /// <summary> + /// Summary description for GeneratorContext. + /// </summary> + public sealed class GeneratorContext : DictionaryBase + { + private EnhanceTypeDelegate m_enhance; + private ScreenInterfacesDelegate m_screenInterfaces; + private IList m_skipInterfaces = new ArrayList(); + + public GeneratorContext() + { + } + + public GeneratorContext(EnhanceTypeDelegate enhanceDelegate, + ScreenInterfacesDelegate screenDelegate) + { + m_enhance = enhanceDelegate; + m_screenInterfaces = screenDelegate; + } + + public EnhanceTypeDelegate EnhanceType + { + get { return m_enhance; } + set { m_enhance = value; } + } + + public ScreenInterfacesDelegate ScreenInterfaces + { + get { return m_screenInterfaces; } + set { m_screenInterfaces = value; } + } + + public bool ShouldSkip( Type interfaceType ) + { + return m_skipInterfaces.Contains( interfaceType ); + } + + public void AddInterfaceToSkip( Type interfaceType ) + { + m_skipInterfaces.Add( interfaceType ); + } + + public object this[ String key ] + { + get { return Dictionary[key]; } + set { Dictionary[key] = value; } + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/IProxyBuilder.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/Builder/IProxyBuilder.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,32 @@ +// 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 CreateCustomInterfaceProxy( Type[] interfaces, GeneratorContext context ); + + Type CreateClassProxy( Type theClass ); + + Type CreateCustomClassProxy( Type theClass, GeneratorContext context ); + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/DynamicProxy.sln ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/DynamicProxy.sln Tue Sep 28 19:27:47 2004 @@ -0,0 +1,29 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Avalon.DynamicProxy", "Apache.Avalon.DynamicProxy.csproj", "{70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Avalon.DynamicProxy.Test", "DynamicProxyTest\Apache.Avalon.DynamicProxy.Test.csproj", "{EF89321E-FB2A-41B6-85B3-794D50A55CF1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}.Debug.ActiveCfg = Debug|.NET + {70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}.Debug.Build.0 = Debug|.NET + {70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}.Release.ActiveCfg = Release|.NET + {70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}.Release.Build.0 = Release|.NET + {EF89321E-FB2A-41B6-85B3-794D50A55CF1}.Debug.ActiveCfg = Debug|.NET + {EF89321E-FB2A-41B6-85B3-794D50A55CF1}.Debug.Build.0 = Debug|.NET + {EF89321E-FB2A-41B6-85B3-794D50A55CF1}.Release.ActiveCfg = Release|.NET + {EF89321E-FB2A-41B6-85B3-794D50A55CF1}.Release.Build.0 = Release|.NET + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/IInvocationHandler.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/IInvocationHandler.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,35 @@ +// 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; + + /// <summary> + /// Defines the handler that will receive all methods + /// invoked on the proxy object. + /// </summary> + public interface IInvocationHandler + { + /// <summary> + /// Implementation should invoke the method on the real object. + /// </summary> + /// <param name="proxy">proxy instance</param> + /// <param name="method"><see cref="System.Reflection.MethodInfo"/> being invoked.</param> + /// <param name="arguments">Arguments of method - if any</param> + /// <returns>Should return the result of method invocation</returns> + object Invoke(object proxy, MethodInfo method, params object[] arguments); + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/ProxyGenerator.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/ProxyGenerator.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,201 @@ +// 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.Emit; + + using Apache.Avalon.DynamicProxy.Builder; + + public delegate void EnhanceTypeDelegate( TypeBuilder mainType, FieldBuilder handlerFieldBuilder, ConstructorBuilder constructorBuilder ); + + public delegate Type[] ScreenInterfacesDelegate( Type[] interfaces ); + + /// <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 = ... + /// ProxyGenerator generator = new ProxyGenerator(); + /// IInterfaceExposed proxy = + /// generator.CreateProxy( new Type[] { typeof(IInterfaceExposed) }, handler ); + /// </code> + /// </example> + public class ProxyGenerator + { + private IProxyBuilder m_builder; + + public ProxyGenerator(IProxyBuilder builder) + { + m_builder = builder; + } + + public ProxyGenerator() : this( new DefaultProxyBuilder() ) + { + } + + public IProxyBuilder ProxyBuilder + { + get { return m_builder; } + set { m_builder = value; } + } + + public virtual object CreateClassProxy(Type baseClass, IInvocationHandler handler) + { + AssertCreateClassProxyArguments(baseClass, handler); + + Type newType = ProxyBuilder.CreateClassProxy(baseClass); + return CreateProxyInstance( newType, handler ); + } + + public virtual object CreateCustomClassProxy(Type baseClass, + IInvocationHandler handler, GeneratorContext context) + { + AssertCreateClassProxyArguments(baseClass, handler, context); + + Type newType = ProxyBuilder.CreateCustomClassProxy(baseClass, context); + return CreateProxyInstance( newType, handler, context ); + } + + /// <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 virtual 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 virtual object CreateProxy(Type[] interfaces, IInvocationHandler handler) + { + AssertCreateProxyArguments(interfaces, handler); + + Type newType = ProxyBuilder.CreateInterfaceProxy(interfaces); + return CreateProxyInstance( newType, handler ); + } + + /// <summary> + /// + /// </summary> + /// <param name="theInterface"></param> + /// <param name="handler"></param> + /// <param name="context"></param> + /// <returns></returns> + public virtual object CreateCustomProxy(Type theInterface, + IInvocationHandler handler, + GeneratorContext context ) + { + return CreateCustomProxy( new Type[] { theInterface }, handler, context ); + } + + /// <summary> + /// + /// </summary> + /// <param name="interfaces"></param> + /// <param name="handler"></param> + /// <param name="context"></param> + /// <returns></returns> + public virtual object CreateCustomProxy(Type[] interfaces, + IInvocationHandler handler, GeneratorContext context ) + { + AssertCreateProxyArguments( interfaces, handler, context ); + Type newType = ProxyBuilder.CreateCustomInterfaceProxy(interfaces, context); + return CreateProxyInstance( newType, handler, context ); + } + + protected virtual object CreateProxyInstance(Type type, IInvocationHandler handler) + { + return Activator.CreateInstance(type, new object[] {handler}); + } + + protected virtual object CreateProxyInstance(Type type, IInvocationHandler handler, GeneratorContext context) + { + return CreateProxyInstance( type, handler ); + } + + protected static void AssertCreateProxyArguments(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"); + } + } + + protected static void AssertCreateProxyArguments(Type[] interfaces, IInvocationHandler handler, GeneratorContext context) + { + AssertCreateProxyArguments(interfaces, handler); + + if (context == null) + { + throw new ArgumentNullException("context"); + } + } + + protected static void AssertCreateClassProxyArguments(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"); + } + } + + protected static void AssertCreateClassProxyArguments(Type baseClass, IInvocationHandler handler, GeneratorContext context) + { + AssertCreateClassProxyArguments(baseClass, handler); + if (context == null) + { + throw new ArgumentNullException("context"); + } + } + } +} \ No newline at end of file Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/StandardInvocationHandler.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxy/StandardInvocationHandler.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,68 @@ +// 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; + + /// <summary> + /// Provides a standard implementation of <see cref="IInvocationHandler"/>. + /// Methods PreInvoke, PostInvoke can be overrided to customize its behavior. + /// </summary> + public class StandardInvocationHandler : IInvocationHandler + { + private object m_target; + + public StandardInvocationHandler(object target) + { + if (target == null) + { + throw new ArgumentNullException("target"); + } + + m_target = target; + } + + protected virtual void PreInvoke(object proxy, System.Reflection.MethodInfo method, params object[] arguments) + { + } + + protected virtual void PostInvoke(object proxy, System.Reflection.MethodInfo method, ref object returnValue, params object[] arguments) + { + } + + #region IInvocationHandler Members + + public virtual object Invoke(object proxy, System.Reflection.MethodInfo method, params object[] arguments) + { + PreInvoke(proxy, method, arguments); + + object returnValue = method.Invoke( Target, arguments ); + + PostInvoke(proxy, method, ref returnValue, arguments); + + return returnValue; + } + + #endregion + + public object Target + { + get + { + return m_target; + } + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj Tue Sep 28 19:27:47 2004 @@ -0,0 +1,181 @@ +<VisualStudioProject> + <CSHARP + ProjectType = "Local" + ProductVersion = "7.10.3077" + SchemaVersion = "2.0" + ProjectGuid = "{EF89321E-FB2A-41B6-85B3-794D50A55CF1}" + > + <Build> + <Settings + ApplicationIcon = "" + AssemblyKeyContainerName = "" + AssemblyName = "Apache.Avalon.DynamicProxy.Test" + AssemblyOriginatorKeyFile = "" + DefaultClientScript = "JScript" + DefaultHTMLPageLayout = "Grid" + DefaultTargetSchema = "IE50" + DelaySign = "false" + OutputType = "Library" + PreBuildEvent = "" + PostBuildEvent = "" + RootNamespace = "Apache.Avalon.DynamicProxy.Test" + RunPostBuildEvent = "OnBuildSuccess" + StartupObject = "" + > + <Config + Name = "Debug" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "DEBUG;TRACE" + DocumentationFile = "" + DebugSymbols = "true" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "false" + OutputPath = "..\..\bin\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + <Config + Name = "Release" + AllowUnsafeBlocks = "false" + BaseAddress = "285212672" + CheckForOverflowUnderflow = "false" + ConfigurationOverrideFile = "" + DefineConstants = "TRACE" + DocumentationFile = "" + DebugSymbols = "false" + FileAlignment = "4096" + IncrementalBuild = "false" + NoStdLib = "false" + NoWarn = "" + Optimize = "true" + OutputPath = "..\..\bin\" + RegisterForComInterop = "false" + RemoveIntegerChecks = "false" + TreatWarningsAsErrors = "false" + WarningLevel = "4" + /> + </Settings> + <References> + <Reference + Name = "System" + AssemblyName = "System" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll" + /> + <Reference + Name = "System.Data" + AssemblyName = "System.Data" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll" + /> + <Reference + Name = "System.XML" + AssemblyName = "System.Xml" + HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll" + /> + <Reference + Name = "DProxy" + Project = "{70EE6AF2-1F6D-4CC5-A1B2-C3182F035F67}" + Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}" + /> + <Reference + Name = "nunit.framework" + AssemblyName = "nunit.framework" + HintPath = "..\..\..\..\..\..\dotnet\NUnit22\bin\nunit.framework.dll" + AssemblyFolderKey = "hklm\dn\nunit.framework" + /> + </References> + </Build> + <Files> + <Include> + <File + RelPath = "AssemblyInfo.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "CachedTypeTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "CustomProxyGeneratorTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "ProxyGeneratorTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "SerializableClassTestCase.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Classes\MySerializableClass.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Classes\NoVirtualMethodClass.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Classes\SealedMethodsClass.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Classes\ServiceClass.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "Classes\SpecializedServiceClass.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + 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 = "ClassInterfaces\ServiceStatusImpl.cs" + SubType = "Code" + BuildAction = "Compile" + /> + </Include> + </Files> + </CSHARP> +</VisualStudioProject> + Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/AssemblyInfo.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/AssemblyInfo.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,27 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Avalon DynamicProxy Test cases")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Avalon DynamicProxy Test cases")] +[assembly: AssemblyCopyright("Copyright (c) 2004 The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("1.0.0.1")] + Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CachedTypeTestCase.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CachedTypeTestCase.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,47 @@ +// 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 +{ + using System; + + using NUnit.Framework; + + using Apache.Avalon.DynamicProxy.Test.Classes; + + /// <summary> + /// Summary description for CachedTypeTestCase. + /// </summary> + [TestFixture] + public class CachedTypeTestCase + { + private ProxyGenerator m_generator = new ProxyGenerator(); + + [Test] + public void CachedClassProxies() + { + object proxy = m_generator.CreateClassProxy( + typeof(ServiceClass), new StandardInvocationHandler( new ServiceClass() ) ); + + Assert.IsNotNull(proxy); + Assert.IsTrue( typeof(ServiceClass).IsAssignableFrom( proxy.GetType() ) ); + + proxy = m_generator.CreateClassProxy( + typeof(ServiceClass), new StandardInvocationHandler( new ServiceClass() ) ); + + Assert.IsNotNull(proxy); + Assert.IsTrue( typeof(ServiceClass).IsAssignableFrom( proxy.GetType() ) ); + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IMyInterface.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IMyInterface.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IMySecondInterface.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/IServiceStatus.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/MyInterfaceImpl.cs Tue Sep 28 19:27:47 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 virtual int Calc(int x, int y) + { + return x + y; + } + + public virtual 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/src/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/MySecondInterfaceImpl.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ClassInterfaces/ServiceStatusImpl.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/Classes/MySerializableClass.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/MySerializableClass.cs Tue Sep 28 19:27:47 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.Classes +{ + using System; + + /// <summary> + /// Summary description for MySerializableClass. + /// </summary> + [Serializable] + public class MySerializableClass + { + public double CalculateSumDistanceNow() + { + return Math.PI; + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/NoVirtualMethodClass.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/NoVirtualMethodClass.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/Classes/SealedMethodsClass.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/SealedMethodsClass.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/Classes/ServiceClass.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/ServiceClass.cs Tue Sep 28 19:27:47 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/src/DynamicProxyTest/Classes/SpecializedServiceClass.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/Classes/SpecializedServiceClass.cs Tue Sep 28 19:27:47 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; + } + } +} Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CustomProxyGeneratorTestCase.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/CustomProxyGeneratorTestCase.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,96 @@ +using Apache.Avalon.DynamicProxy.Test.Classes; +// 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 +{ + using System; + using System.Reflection.Emit; + + using NUnit.Framework; + + using Apache.Avalon.DynamicProxy.Test.ClassInterfaces; + + /// <summary> + /// Summary description for CustomProxyGeneratorTestCase. + /// </summary> + [TestFixture] + public class CustomProxyGeneratorTestCase : Assertion + { + private ProxyGenerator m_generator; + private bool m_enhanceInvoked; + private bool m_screenInvoked; + + [SetUp] + public void Init() + { + m_generator = new ProxyGenerator(); + m_enhanceInvoked = false; + m_screenInvoked = false; + } + + [Test] + public void CreateCustomProxy() + { + GeneratorContext context = new GeneratorContext( + new EnhanceTypeDelegate(EnhanceType), + new ScreenInterfacesDelegate(ScreenInterfaces)); + + object proxy = m_generator.CreateCustomProxy( + typeof (IMyInterface), + new StandardInvocationHandler(new MyInterfaceImpl()), context); + + Assert( m_enhanceInvoked ); + Assert( m_screenInvoked ); + } + + [Test] + public void CreateCustomClassProxy() + { + GeneratorContext context = new GeneratorContext( + new EnhanceTypeDelegate(EnhanceType), + new ScreenInterfacesDelegate(ScreenInterfaces)); + + object proxy = m_generator.CreateCustomClassProxy( + typeof (ServiceClass), + new StandardInvocationHandler(new ServiceClass()), + context); + + Assert( m_enhanceInvoked ); + Assert( m_screenInvoked ); + } + + private void EnhanceType(TypeBuilder mainType, FieldBuilder handlerFieldBuilder, ConstructorBuilder constructorBuilder) + { + Assert( !m_enhanceInvoked ); + + AssertNotNull(mainType); + AssertNotNull(handlerFieldBuilder); + AssertNotNull(constructorBuilder); + + m_enhanceInvoked = true; + } + + private Type[] ScreenInterfaces(Type[] interfaces) + { + Assert( !m_screenInvoked ); + + AssertNotNull(interfaces); + + m_screenInvoked = true; + + return interfaces; + } + } +} \ No newline at end of file Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ProxyGeneratorTestCase.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/ProxyGeneratorTestCase.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,239 @@ +// 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 +{ + using System; + using System.Reflection; + + using NUnit.Framework; + + using Apache.Avalon.DynamicProxy; + using Apache.Avalon.DynamicProxy.Test.Classes; + using Apache.Avalon.DynamicProxy.Test.ClassInterfaces; + + /// <summary> + /// Summary description for ProxyGeneratorTestCase. + /// </summary> + [TestFixture] + public class ProxyGeneratorTestCase : Assertion + { + private ProxyGenerator m_generator; + + [SetUp] + public void Init() + { + m_generator = new ProxyGenerator(); + } + + [Test] + public void ProxyForClass() + { + object proxy = m_generator.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 = m_generator.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 ProxyForClassWhichImplementsInterfaces() + { + object proxy = m_generator.CreateClassProxy( + typeof(MyInterfaceImpl), new ResultModifiedInvocationHandler( new MyInterfaceImpl() ) ); + + AssertNotNull( proxy ); + Assert( typeof(MyInterfaceImpl).IsAssignableFrom( proxy.GetType() ) ); + Assert( typeof(IMyInterface).IsAssignableFrom( proxy.GetType() ) ); + + IMyInterface inter = (IMyInterface) proxy; + + AssertEquals( 44, inter.Calc( 20, 25 ) ); + } + + [Test] + public void ProxyingClassWithoutVirtualMethods() + { + object proxy = m_generator.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 = m_generator.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 + { + m_generator.CreateClassProxy( + typeof(ICloneable), new StandardInvocationHandler( new SpecializedServiceClass() ) ); + } + catch(ArgumentException) + { + // Expected + } + + try + { + m_generator.CreateClassProxy( + null, new StandardInvocationHandler( new SpecializedServiceClass() ) ); + } + catch(ArgumentNullException) + { + // Expected + } + + try + { + m_generator.CreateClassProxy( + typeof(SpecializedServiceClass), null ); + } + catch(ArgumentNullException) + { + // Expected + } + } + + [Test] + public void TestGenerationSimpleInterface() + { + object proxy = m_generator.CreateProxy( + typeof(IMyInterface), new StandardInvocationHandler( new MyInterfaceImpl() ) ); + + AssertNotNull( proxy ); + Assert( typeof(IMyInterface).IsAssignableFrom( proxy.GetType() ) ); + + IMyInterface inter = (IMyInterface) proxy; + + AssertEquals( 45, inter.Calc( 20, 25 ) ); + + inter.Name = "opa"; + AssertEquals( "opa", inter.Name ); + + inter.Started = true; + AssertEquals( true, inter.Started ); + } + + [Test] + public void TestGenerationWithInterfaceHeritage() + { + object proxy = m_generator.CreateProxy( + typeof(IMySecondInterface), new StandardInvocationHandler( new MySecondInterfaceImpl() ) ); + + AssertNotNull( proxy ); + Assert( typeof(IMyInterface).IsAssignableFrom( proxy.GetType() ) ); + Assert( typeof(IMySecondInterface).IsAssignableFrom( proxy.GetType() ) ); + + IMySecondInterface inter = (IMySecondInterface) proxy; + inter.Calc(1, 1); + + inter.Name = "hammett"; + AssertEquals( "hammett", inter.Name ); + + inter.Address = "pereira leite, 44"; + AssertEquals( "pereira leite, 44", inter.Address ); + + AssertEquals( 45, inter.Calc( 20, 25 ) ); + } + + [Test] + public void TestEnumProperties() + { + ServiceStatusImpl service = new ServiceStatusImpl(); + + object proxy = m_generator.CreateProxy( + typeof(IServiceStatus), new StandardInvocationHandler( service ) ); + + AssertNotNull( proxy ); + Assert( typeof(IServiceStatus).IsAssignableFrom( proxy.GetType() ) ); + + IServiceStatus inter = (IServiceStatus) proxy; + AssertEquals( State.Invalid, inter.ActualState ); + + inter.ChangeState( State.Valid ); + AssertEquals( State.Valid, inter.ActualState ); + } + + public class MyInterfaceProxy : IInvocationHandler + { + #region IInvocationHandler Members + + public object Invoke(object proxy, MethodInfo method, params object[] arguments) + { + return null; + } + + #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; + } + } + } +} + + Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/SerializableClassTestCase.cs ============================================================================== --- (empty file) +++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/src/DynamicProxyTest/SerializableClassTestCase.cs Tue Sep 28 19:27:47 2004 @@ -0,0 +1,41 @@ +// 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 +{ + using System; + + using NUnit.Framework; + + using Apache.Avalon.DynamicProxy.Test.Classes; + + /// <summary> + /// Summary description for SerializableClassTestCase. + /// </summary> + [TestFixture] + public class SerializableClassTestCase : Assertion + { + [Test] + public void CreateSerializable() + { + MySerializableClass myClass = new MySerializableClass(); + + ProxyGenerator generator = new ProxyGenerator(); + MySerializableClass proxy = (MySerializableClass) + generator.CreateClassProxy( typeof(MySerializableClass), new StandardInvocationHandler(myClass) ); + + Assert( proxy.GetType().IsSerializable ); + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]