svn commit: rev 43496 - in avalon/trunk/central/laboratory/avalon-net/DynamicProxy: . Builder Builder/CodeGenerators DynamicProxyTest
[email protected] 8 Sep 2004 04:04:05 -0000
| Newsgroups | gmane.comp.jakarta.avalon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: hammett
Date: Tue Sep 7 21:04:03 2004
New Revision: 43496
Added:
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/CustomProxyGeneratorTestCase.cs (contents, props changed)
Modified:
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/Apache.Avalon.DynamicProxy.Test.csproj
avalon/trunk/central/laboratory/avalon-net/DynamicProxy/ProxyGenerator.cs
Log:
Dynamic Proxy now supports customization during the proxy code generation.
Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs (original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/BaseCodeGenerator.cs Tue Sep 7 21:04:03 2004
@@ -26,8 +26,33 @@
{
private TypeBuilder m_typeBuilder;
private FieldBuilder m_handlerField;
+ private ConstructorBuilder m_constBuilder;
private IList m_generated = new ArrayList();
+ private EnhanceTypeDelegate m_enhanceDelegate;
+ private ScreenInterfacesDelegate m_screenInterfacesDelegate;
+
+ protected BaseCodeGenerator()
+ {
+ }
+
+ protected BaseCodeGenerator(EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces)
+ {
+ m_enhanceDelegate = enhance;
+ m_screenInterfacesDelegate = screenInterfaces;
+ }
+
+ protected EnhanceTypeDelegate EnhanceTypeDelegate
+ {
+ get { return m_enhanceDelegate; }
+ }
+
+ protected ScreenInterfacesDelegate ScreenInterfacesDelegate
+ {
+ get { return m_screenInterfacesDelegate; }
+ }
+
protected TypeBuilder MainTypeBuilder
{
get { return m_typeBuilder; }
@@ -38,6 +63,11 @@
get { return m_handlerField; }
}
+ protected ConstructorBuilder DefaultConstructorBuilder
+ {
+ get { return m_constBuilder; }
+ }
+
protected virtual ModuleBuilder CreateDynamicModule()
{
AssemblyName assemblyName = new AssemblyName();
@@ -59,7 +89,7 @@
"ProxyType", TypeAttributes.Public | TypeAttributes.Class, baseType, interfaces);
m_handlerField = GenerateField();
- ConstructorBuilder constr = GenerateConstructor();
+ m_constBuilder = GenerateConstructor();
return m_typeBuilder;
}
@@ -129,6 +159,7 @@
if (!ignoreInterfaces)
{
Type[] baseInterfaces = type.FindInterfaces(new TypeFilter(NoFilterImpl), type);
+
GenerateInterfaceImplementation(baseInterfaces);
}
Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs (original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/ClassProxyGenerator.cs Tue Sep 7 21:04:03 2004
@@ -21,12 +21,31 @@
/// </summary>
public class ClassProxyGenerator : BaseCodeGenerator
{
+ public ClassProxyGenerator() : base()
+ {
+ }
+
+ public ClassProxyGenerator(EnhanceTypeDelegate enhance, ScreenInterfacesDelegate screenInterfaces) :
+ base(enhance, screenInterfaces)
+ {
+ }
+
public Type GenerateCode(Type baseClass)
{
- // TODO: interfaces of base class
-
- CreateTypeBuilder( baseClass, new Type[0] );
+ Type[] interfaces = new Type[0];
+
+ if (ScreenInterfacesDelegate != null)
+ {
+ interfaces = ScreenInterfacesDelegate(interfaces);
+ }
+
+ CreateTypeBuilder( baseClass, interfaces );
GenerateTypeImplementation( baseClass, true );
+
+ if (EnhanceTypeDelegate != null)
+ {
+ EnhanceTypeDelegate(MainTypeBuilder, HandlerFieldBuilder, DefaultConstructorBuilder);
+ }
return MainTypeBuilder.CreateType();
}
Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs (original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/CodeGenerators/InterfaceProxyGenerator.cs Tue Sep 7 21:04:03 2004
@@ -23,14 +23,31 @@
/// </summary>
public class InterfaceProxyGenerator : BaseCodeGenerator
{
- public InterfaceProxyGenerator()
+ public InterfaceProxyGenerator() : base()
{
}
+ public InterfaceProxyGenerator(EnhanceTypeDelegate enhance, ScreenInterfacesDelegate screenInterfaces) :
+ base(enhance, screenInterfaces)
+ {
+
+ }
+
public Type GenerateCode(Type[] interfaces)
{
+ if (ScreenInterfacesDelegate != null)
+ {
+ interfaces = ScreenInterfacesDelegate(interfaces);
+ }
+
CreateTypeBuilder( null, interfaces );
GenerateInterfaceImplementation( interfaces );
+
+ if (EnhanceTypeDelegate != null)
+ {
+ EnhanceTypeDelegate(MainTypeBuilder, HandlerFieldBuilder, DefaultConstructorBuilder);
+ }
+
return MainTypeBuilder.CreateType();
}
}
Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs (original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/IProxyBuilder.cs Tue Sep 7 21:04:03 2004
@@ -23,6 +23,12 @@
{
Type CreateInterfaceProxy( Type[] interfaces );
+ Type CreateCustomInterfaceProxy( Type[] interfaces, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces );
+
Type CreateClassProxy( Type theClass );
+
+ Type CreateCustomClassProxy( Type theClass, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces );
}
}
Modified: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs
==============================================================================
--- avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs (original)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/Builder/ProxyBuilderImpl.cs Tue Sep 7 21:04:03 2004
@@ -36,6 +36,20 @@
return generator.GenerateCode( theClass );
}
+ public Type CreateCustomInterfaceProxy(Type[] interfaces, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces)
+ {
+ InterfaceProxyGenerator generator = new InterfaceProxyGenerator(enhance, screenInterfaces);
+ return generator.GenerateCode( interfaces );
+ }
+
+ public Type CreateCustomClassProxy(Type theClass, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces)
+ {
+ ClassProxyGenerator generator = new ClassProxyGenerator(enhance, screenInterfaces);
+ 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 Tue Sep 7 21:04:03 2004
@@ -99,6 +99,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "CustomProxyGeneratorTestCase.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "ProxyGeneratorTestCase.cs"
SubType = "Code"
BuildAction = "Compile"
Added: avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/CustomProxyGeneratorTestCase.cs
==============================================================================
--- (empty file)
+++ avalon/trunk/central/laboratory/avalon-net/DynamicProxy/DynamicProxyTest/CustomProxyGeneratorTestCase.cs Tue Sep 7 21:04:03 2004
@@ -0,0 +1,107 @@
+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 bool m_enhanceInvoked;
+ private bool m_screenInvoked;
+ private bool m_constructorInvoked;
+
+ [SetUp]
+ public void Init()
+ {
+ m_enhanceInvoked = false;
+ m_screenInvoked = false;
+ m_constructorInvoked = false;
+ }
+
+ [Test]
+ public void CreateCustomProxy()
+ {
+ object proxy = ProxyGenerator.CreateCustomProxy(
+ typeof (IMyInterface),
+ new StandardInvocationHandler(new MyInterfaceImpl()),
+ new EnhanceTypeDelegate(EnhanceType),
+ new ScreenInterfacesDelegate(ScreenInterfaces),
+ new ConstructorArgumentsDelegate(BuildConstructorArguments));
+
+ Assert( m_enhanceInvoked );
+ Assert( m_screenInvoked );
+ Assert( m_constructorInvoked );
+ }
+
+ [Test]
+ public void CreateCustomClassProxy()
+ {
+ object proxy = ProxyGenerator.CreateCustomClassProxy(
+ typeof (ServiceClass),
+ new StandardInvocationHandler(new ServiceClass()),
+ new EnhanceTypeDelegate(EnhanceType),
+ new ScreenInterfacesDelegate(ScreenInterfaces),
+ new ConstructorArgumentsDelegate(BuildConstructorArguments));
+
+ Assert( m_enhanceInvoked );
+ Assert( m_screenInvoked );
+ Assert( m_constructorInvoked );
+ }
+
+ 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;
+ }
+
+ private object[] BuildConstructorArguments(Type generatedType, IInvocationHandler handler)
+ {
+ Assert( !m_constructorInvoked );
+
+ AssertNotNull( generatedType );
+ AssertNotNull( handler );
+
+ m_constructorInvoked = true;
+
+ return new object[] { handler };
+ }
+ }
+}
\ No newline at end of file
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 Tue Sep 7 21:04:03 2004
@@ -1,4 +1,4 @@
- // Copyright 2004 The Apache Software Foundation
+// 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.
@@ -15,11 +15,16 @@
namespace Apache.Avalon.DynamicProxy
{
using System;
- using System.Reflection;
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 );
+
+ public delegate object[] ConstructorArgumentsDelegate( Type generatedType, IInvocationHandler handler );
+
/// <summary>
/// Generates a Java style proxy. This overrides the .Net proxy requirements
/// that forces one to extend MarshalByRefObject or (for a different purpose)
@@ -53,23 +58,23 @@
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");
- }
+ AssertCreateClassProxyArguments(baseClass, handler);
Type newType = ProxyBuilder.CreateClassProxy(baseClass);
return CreateProxyInstance( newType, handler );
}
+ public static object CreateCustomClassProxy(Type baseClass, IInvocationHandler handler,
+ EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces,
+ ConstructorArgumentsDelegate constructorArguments)
+ {
+ AssertCreateClassProxyArguments(baseClass, handler);
+
+ Type newType = ProxyBuilder.CreateCustomClassProxy(baseClass, enhance, screenInterfaces);
+ return CreateCustomProxyInstance( newType, handler, constructorArguments );
+ }
+
/// <summary>
/// Generates a proxy implementing all the specified interfaces and
/// redirecting method invocations to the specifed handler.
@@ -91,6 +96,69 @@
/// <returns>Proxy instance</returns>
public static 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="enhance"></param>
+ /// <param name="screenInterfaces"></param>
+ /// <param name="constructorArguments"></param>
+ /// <returns></returns>
+ public static object CreateCustomProxy(Type theInterface,
+ IInvocationHandler handler, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces,
+ ConstructorArgumentsDelegate constructorArguments )
+ {
+ return CreateCustomProxy( new Type[] { theInterface }, handler,
+ enhance, screenInterfaces, constructorArguments );
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="interfaces"></param>
+ /// <param name="handler"></param>
+ /// <param name="enhance"></param>
+ /// <param name="screenInterfaces"></param>
+ /// <param name="constructorArguments"></param>
+ /// <returns></returns>
+ public static object CreateCustomProxy(Type[] interfaces,
+ IInvocationHandler handler, EnhanceTypeDelegate enhance,
+ ScreenInterfacesDelegate screenInterfaces,
+ ConstructorArgumentsDelegate constructorArguments )
+ {
+ AssertCreateProxyArguments( interfaces, handler);
+ Type newType = ProxyBuilder.CreateCustomInterfaceProxy(interfaces, enhance, screenInterfaces);
+ return CreateCustomProxyInstance( newType, handler, constructorArguments );
+ }
+
+ private static object CreateProxyInstance(Type type, IInvocationHandler handler)
+ {
+ return Activator.CreateInstance(type, new object[] {handler});
+ }
+
+ private static object CreateCustomProxyInstance(Type type, IInvocationHandler handler, ConstructorArgumentsDelegate constructorArguments)
+ {
+ if (constructorArguments != null)
+ {
+ object[] arguments = constructorArguments( type, handler );
+ return Activator.CreateInstance(type, arguments);
+ }
+ else
+ {
+ return CreateProxyInstance( type, handler );
+ }
+ }
+
+ private static void AssertCreateProxyArguments(Type[] interfaces, IInvocationHandler handler)
+ {
if (interfaces == null)
{
throw new ArgumentNullException("interfaces");
@@ -103,14 +171,22 @@
{
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)
+ private static void AssertCreateClassProxyArguments(Type baseClass, IInvocationHandler handler)
{
- return Activator.CreateInstance(type, new object[] {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");
+ }
}
}
}