Update of /cvsroot/mocklib/netmocklib/input/src/Proxy
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11532/input/src/Proxy
Added Files:
DynamicProxyTest.cs IProxyInvocationHandler.cs
MetaDataFactory.cs Proxy.cs ProxyFactory.cs SecurityManager.cs
SecurityProxy.cs
Log Message:
no message
--- NEW FILE: Proxy.cs ---
using System;
namespace DynamicProxy
{
/// <summary>
/// Summary description for Proxy.
/// </summary>
public class Proxy
{
private Proxy() {
}
public static InvocationHandler GetInvocationHandler(Object proxy) {
throw NotImplementedException("not implemented yet, sorry");
}
public static Class GetProxyClass(ClassLoader loader, Type[] interfaces) {
throw NotImplementedException("not implemented yet, sorry");
}
public static boolean isProxyClass(Type cl) {
throw NotImplementedException("not implemented yet, sorry");
}
public static object newProxyInstance(Type[] interfaces, IProxyInvocationHandler h)
{
if(interfaces == null)
throw new ArgumentException("interfaces cannot be null");
else if(h == null)
throw new ArgumentException("h cannot be null");
else if(interfaces.Length < 1)
throw new ArgumentException("interfaces array cannot be empty");
else if(interfaces.Length > 1)
throw new NotImplementedException("Sorry, creating a class implementing multiple interfaces is not implemented yet");
ProxyFactory.GetInstance().Create(h, interfaces[0]);
}
}
}
--- NEW FILE: ProxyFactory.cs ---
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace DynamicProxy
{
/// <summary>
/// </summary>
public class ProxyFactory
{
private static ProxyFactory instance;
private static Object lockObj = new Object();
private Hashtable typeMap = Hashtable.Synchronized( new Hashtable() );
private static readonly Hashtable opCodeTypeMapper = new Hashtable();
private const string PROXY_SUFFIX = "Proxy";
private const string ASSEMBLY_NAME = "ProxyAssembly";
private const string MODULE_NAME = "ProxyModule";
private const string HANDLER_NAME = "handler";
// Initialize the value type mapper. This is needed for methods with intrinsic
// return types, used in the Emit process.
static ProxyFactory() {
opCodeTypeMapper.Add( typeof( System.Boolean ), OpCodes.Ldind_I1 );
opCodeTypeMapper.Add( typeof( System.Int16 ), OpCodes.Ldind_I2 );
opCodeTypeMapper.Add( typeof( System.Int32 ), OpCodes.Ldind_I4 );
opCodeTypeMapper.Add( typeof( System.Int64 ), OpCodes.Ldind_I8 );
opCodeTypeMapper.Add( typeof( System.Double ), OpCodes.Ldind_R8 );
opCodeTypeMapper.Add( typeof( System.Single ), OpCodes.Ldind_R4 );
opCodeTypeMapper.Add( typeof( System.UInt16 ), OpCodes.Ldind_U2 );
opCodeTypeMapper.Add( typeof( System.UInt32 ), OpCodes.Ldind_U4 );
}
private ProxyFactory() {
}
public static ProxyFactory GetInstance() {
if ( instance == null ) {
CreateInstance();
}
return instance;
}
private static void CreateInstance() {
lock ( lockObj ) {
if ( instance == null ) {
instance = new ProxyFactory();
}
}
}
public Object Create( IProxyInvocationHandler handler, Type objType, bool isObjInterface ) {
string typeName = objType.FullName + PROXY_SUFFIX;
Type type = (Type)typeMap[ typeName ];
// check to see if the type was in the cache. If the type was not cached, then
// create a new instance of the dynamic type and add it to the cache.
if ( type == null ) {
if ( isObjInterface ) {
type = CreateType( handler, new Type[] { objType }, typeName );
} else {
type = CreateType( handler, objType.GetInterfaces(), typeName );
}
typeMap.Add( typeName, type );
}
// return a new instance of the type.
return Activator.CreateInstance( type, new object[] { handler } );
}
public Object Create( IProxyInvocationHandler handler, Type objType ) {
return Create( handler, objType, false );
}
private Type CreateType( IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName ) {
Type retVal = null;
if ( handler != null && interfaces != null ) {
Type objType = typeof( System.Object );
Type handlerType = typeof( IProxyInvocationHandler );
AppDomain domain = Thread.GetDomain();
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = ASSEMBLY_NAME;
assemblyName.Version = new Version( 1, 0, 0, 0 );
// create a new assembly for this proxy, one that isn't presisted on the file system
AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run );
// create a new module for this proxy
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule( MODULE_NAME );
// Set the class to be public and sealed
TypeAttributes typeAttributes =
TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
// Gather up the proxy information and create a new type builder. One that
// inherits from Object and implements the interface passed in
TypeBuilder typeBuilder = moduleBuilder.DefineType(
dynamicTypeName, typeAttributes, objType, interfaces );
// Define a member variable to hold the delegate
FieldBuilder handlerField = typeBuilder.DefineField(
HANDLER_NAME, handlerType, FieldAttributes.Private );
// build a constructor that takes the delegate object as the only argument
//ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] );
ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]);
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType } );
#region( "Constructor IL Code" )
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
// Load "this"
constructorIL.Emit( OpCodes.Ldarg_0 );
// Load first constructor parameter
constructorIL.Emit( OpCodes.Ldarg_1 );
// Set the first parameter into the handler field
constructorIL.Emit( OpCodes.Stfld, handlerField );
// Load "this"
constructorIL.Emit( OpCodes.Ldarg_0 );
// Call the super constructor
constructorIL.Emit( OpCodes.Call, superConstructor );
// Constructor return
constructorIL.Emit( OpCodes.Ret );
#endregion
// for every method that the interfaces define, build a corresponding
// method in the dynamic type that calls the handlers invoke method.
foreach ( Type interfaceType in interfaces ) {
GenerateMethod( interfaceType, handlerField, typeBuilder );
}
retVal = typeBuilder.CreateType();
}
return retVal;
}
private void GenerateMethod( Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder ) {
MetaDataFactory.Add( interfaceType );
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
if ( interfaceMethods != null ) {
for ( int i = 0; i < interfaceMethods.Length; i++ ) {
MethodInfo methodInfo = interfaceMethods[i];
// Get the method parameters since we need to create an array
// of parameter types
ParameterInfo[] methodParams = methodInfo.GetParameters();
int numOfParams = methodParams.Length;
Type[] methodParameters = new Type[ numOfParams ];
// convert the ParameterInfo objects into Type
for ( int j = 0; j < numOfParams; j++ ) {
methodParameters[j] = methodParams[j].ParameterType;
}
// create a new builder for the method in the interface
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
methodInfo.Name,
MethodAttributes.Public | MethodAttributes.Virtual,
CallingConventions.Standard,
methodInfo.ReturnType, methodParameters );
#region( "Handler Method IL Code" )
ILGenerator methodIL = methodBuilder.GetILGenerator();
// Emit a declaration of a local variable if there is a return
// type defined
if ( !methodInfo.ReturnType.Equals( typeof( void ) ) ) {
methodIL.DeclareLocal( methodInfo.ReturnType );
if ( methodInfo.ReturnType.IsValueType && !methodInfo.ReturnType.IsPrimitive ) {
methodIL.DeclareLocal( methodInfo.ReturnType );
}
}
// if we have any parameters for the method, then declare an
// Object array local var.
if ( numOfParams > 0 ) {
methodIL.DeclareLocal( typeof( System.Object[] ) );
}
// declare a label for invoking the handler
Label handlerLabel = methodIL.DefineLabel();
// declare a lable for returning from the mething
Label returnLabel = methodIL.DefineLabel();
// load "this"
methodIL.Emit( OpCodes.Ldarg_0 );
// load the handler instance variable
methodIL.Emit( OpCodes.Ldfld, handlerField );
// jump to the handlerLabel if the handler instance variable is not null
methodIL.Emit( OpCodes.Brtrue_S, handlerLabel );
// the handler is null, so return null if the return type of
// the method is not void, otherwise return nothing
if ( !methodInfo.ReturnType.Equals( typeof( void ) ) ) {
if ( methodInfo.ReturnType.IsValueType && !methodInfo.ReturnType.IsPrimitive && !methodInfo.ReturnType.IsEnum ) {
methodIL.Emit( OpCodes.Ldloc_1 );
} else {
// load null onto the stack
methodIL.Emit( OpCodes.Ldnull );
}
// store the null return value
methodIL.Emit( OpCodes.Stloc_0 );
// jump to return
methodIL.Emit( OpCodes.Br_S, returnLabel );
}
// the handler is not null, so continue with execution
methodIL.MarkLabel( handlerLabel );
// load "this"
methodIL.Emit( OpCodes.Ldarg_0 );
// load the handler
methodIL.Emit( OpCodes.Ldfld, handlerField );
// load "this" since its needed for the call to invoke
methodIL.Emit( OpCodes.Ldarg_0 );
// load the name of the interface, used to get the MethodInfo object
// from MetaDataFactory
methodIL.Emit( OpCodes.Ldstr, interfaceType.FullName );
// load the index, used to get the MethodInfo object
// from MetaDataFactory
methodIL.Emit( OpCodes.Ldc_I4, i );
// invoke GetMethod in MetaDataFactory
methodIL.Emit( OpCodes.Call,
typeof( DynamicProxy.MetaDataFactory ).GetMethod(
"GetMethod", new Type[] { typeof( string ), typeof( int ) } ) );
// load the number of parameters onto the stack
methodIL.Emit( OpCodes.Ldc_I4, numOfParams );
// create a new array, using the size that was just pused on the stack
methodIL.Emit( OpCodes.Newarr, typeof( System.Object ) );
// if we have any parameters, then iterate through and set the values
// of each element to the corresponding arguments
if ( numOfParams > 0 ) {
methodIL.Emit( OpCodes.Stloc_1 );
for ( int j = 0; j < numOfParams; j++ ) {
methodIL.Emit( OpCodes.Ldloc_1 );
methodIL.Emit( OpCodes.Ldc_I4, j );
methodIL.Emit( OpCodes.Ldarg, j + 1 );
if ( methodParameters[j].IsValueType ) {
methodIL.Emit( OpCodes.Box, methodParameters[j] );
}
methodIL.Emit( OpCodes.Stelem_Ref );
}
methodIL.Emit( OpCodes.Ldloc_1 );
}
// call the Invoke method
methodIL.Emit( OpCodes.Callvirt,
typeof( DynamicProxy.IProxyInvocationHandler ).GetMethod( "Invoke" ) );
if ( !methodInfo.ReturnType.Equals( typeof( void ) ) ) {
// if the return type if a value type, then unbox the return value
// so that we don't get junk.
if ( methodInfo.ReturnType.IsValueType ) {
methodIL.Emit( OpCodes.Unbox, methodInfo.ReturnType );
if ( methodInfo.ReturnType.IsEnum ) {
methodIL.Emit( OpCodes.Ldind_I4 );
} else if ( !methodInfo.ReturnType.IsPrimitive ) {
methodIL.Emit( OpCodes.Ldobj, methodInfo.ReturnType );
} else {
methodIL.Emit( (OpCode) opCodeTypeMapper[ methodInfo.ReturnType ] );
}
}
// store the result
methodIL.Emit( OpCodes.Stloc_0 );
// jump to the return statement
methodIL.Emit( OpCodes.Br_S, returnLabel );
// mark the return statement
methodIL.MarkLabel( returnLabel );
// load the value stored before we return. This will either be
// null (if the handler was null) or the return value from Invoke
methodIL.Emit( OpCodes.Ldloc_0 );
} else {
// pop the return value that Invoke returned from the stack since
// the method's return type is void.
methodIL.Emit( OpCodes.Pop );
//mark the return statement
methodIL.MarkLabel( returnLabel );
}
// Return
methodIL.Emit( OpCodes.Ret );
#endregion
}
}
// Iterate through the parent interfaces and recursively call this method
foreach ( Type parentType in interfaceType.GetInterfaces() ) {
GenerateMethod( parentType, handlerField, typeBuilder );
}
}
}
}
--- NEW FILE: SecurityProxy.cs ---
using System;
namespace DynamicProxy
{
/// <summary>
/// Test proxy invocation handler which is used to check a methods security
/// before invoking the method
/// </summary>
public class SecurityProxy : IProxyInvocationHandler
{
Object obj = null;
///<summary>
/// Class constructor
///</summary>
///<param name="obj">Instance of object to be proxied</param>
private SecurityProxy( Object obj ) {
this.obj = obj;
}
///<summary>
/// Factory method to create a new proxy instance.
///</summary>
///<param name="obj">Instance of object to be proxied</param>
public static Object NewInstance( Object obj ) {
return ProxyFactory.GetInstance().Create(
new SecurityProxy( obj ), obj.GetType() );
}
///<summary>
/// IProxyInvocationHandler method that gets called from within the proxy
/// instance.
///</summary>
///<param name="proxy">Instance of proxy</param>
///<param name="method">Method instance
public Object Invoke(Object proxy, System.Reflection.MethodInfo method, Object[] parameters) {
Object retVal = null;
string userRole = "role";
// if the user has permission to invoke the method, the method
// is invoked, otherwise an exception is thrown indicating they
// do not have permission
if ( SecurityManager.IsMethodInRole( userRole, method.Name ) ) {
// The actual method is invoked
retVal = method.Invoke( obj, parameters );
} else {
throw new Exception( "Invalid permission to invoke " + method.Name );
}
return retVal;
}
}
}
--- NEW FILE: SecurityManager.cs ---
using System;
namespace DynamicProxy
{
/// <summary>
/// Test class.
/// </summary>
public class SecurityManager
{
///<summary>
/// Class constructor
///</summary>
public SecurityManager() {
}
///<summary>
/// Test method which can be implemented to check if a given method can
/// be accessed by a user given the following role.
/// NOTE: This does not have any implementation...it's only used as a placeholder
///</summary>
public static bool IsMethodInRole( string userRole, string methodName ) {
// check if the specified user role can invoke the method
return true;
}
}
}
--- NEW FILE: MetaDataFactory.cs ---
using System;
using System.Reflection;
using System.Collections;
namespace DynamicProxy
{
/// <summary>
/// Factory class used to cache Types instances
/// </summary>
public class MetaDataFactory
{
private static Hashtable typeMap = new Hashtable();
/// <summary>
/// Class constructor. Private because this is a static class.
/// </summary>
private MetaDataFactory() {
}
///<summary>
/// Method to add a new Type to the cache, using the type's fully qualified
/// name as the key
///</summary>
///<param name="interfaceType">Type to cache</param>
public static void Add( Type interfaceType ) {
if ( interfaceType != null ) {
lock ( typeMap.SyncRoot ) {
if ( !typeMap.ContainsKey( interfaceType.FullName ) ) {
typeMap.Add( interfaceType.FullName, interfaceType );
}
}
}
}
///<summary>
/// Method to return the method of a given type at a specified index.
///</summary>
///<param name="name">Fully qualified name of the method to return</param>
///<param name="i">Index to use to return MethodInfo</param>
///<returns>MethodInfo</returns>
public static MethodInfo GetMethod( string name, int i ) {
Type type = null;
lock ( typeMap.SyncRoot ) {
type = (Type) typeMap[ name ];
}
MethodInfo[] methods = type.GetMethods();
if ( i < methods.Length ) {
return methods[i];
}
return null;
}
}
}
--- NEW FILE: DynamicProxyTest.cs ---
using System;
namespace DynamicProxy
{
/// <summary>
/// </summary>
public class TestBed
{
/// <summary>
/// </summary>
[STAThread]
static void Main( string[] args ) {
ITest test = (ITest)SecurityProxy.NewInstance( new TestImpl() );
test.TestFunctionOne();
test.TestFunctionTwo( new Object(), new Object() );
}
}
public interface ITest {
void TestFunctionOne();
Object TestFunctionTwo( Object a, Object b );
}
public class TestImpl : ITest {
public void TestFunctionOne() {
Console.WriteLine( "In TestImpl.TestFunctionOne()" );
}
public Object TestFunctionTwo( Object a, Object b ) {
Console.WriteLine( "In TestImpl.TestFunctionTwo( Object a, Object b )" );
return null;
}
}
}
--- NEW FILE: IProxyInvocationHandler.cs ---
using System;
using System.Reflection;
namespace DynamicProxy
{
/// <summary>
/// Interface that a user defined proxy handler needs to implement. This interface
/// defines one method that gets invoked by the generated proxy.
/// </summary>
public interface IProxyInvocationHandler
{
/// <param name="proxy">The instance of the proxy</param>
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
/// <param name="parameters">Parameters to pass to the method</param>
/// <returns>Object</returns>
Object Invoke( Object proxy, MethodInfo method, Object[] parameters );
}
}
|