#region Delegates
public delegate object InvocationDelegate(object target
, System.Reflection.MethodBase method
, object[] parameters);
#endregion Delegates
public interface IDynamicProxy
{
#region Properties
InvocationDelegate InvocationHandler
{
get;
set;
}
object ProxyTarget
{
get;
set;
}
bool Strict
{
get;
set;
}
Type[] SupportedTypes
{
get;
set;
}
#endregion Properties
}
public class DynamicProxyFactory
{
#region Fields
private static string Interface_DefaultNameSpace = "L.D.P.A.C";
private static Dictionary<string, Type> Interface_HashTypes = new Dictionary<string, Type>();
#endregion Fields
#region Constructors
private DynamicProxyFactory()
{
}
#endregion Constructors
#region Methods
public static INTERFACE CreateImplement<INTERFACE>(object instance)
where INTERFACE : class
{
return CreateImplement(typeof(INTERFACE), instance) as INTERFACE;
}
public static object CreateImplement(Type interfaceType, object inpmlementInstance)
{
if (null == interfaceType)
{
throw new ArgumentException("The first parameter must not be null!");
}
if (null == inpmlementInstance)
{
return CreateImplement(interfaceType);
}
else
{
Type type = GenerateInterfaceImplementType(interfaceType, inpmlementInstance.GetType());
return Activator.CreateInstance(type, inpmlementInstance);
}
}
public static object CreateImplement(Type interfaceType)
{
if (null == interfaceType)
{
throw new ArgumentException("The first parameter must not be null!");
}
if (interfaceType.IsInterface)
{
Type type = GenerateInterfaceImplementType(interfaceType, null);
return Activator.CreateInstance(type);
}
else
{
//Guess interface
Type[] ints = interfaceType.GetInterfaces();
if (null == ints)
{
throw new ArgumentException(interfaceType.FullName + ": could not found the interface it derived.");
}
if (ints.Length > 1)
{
throw new ArgumentException(interfaceType.FullName + ": More than one interfaces it derived.");
}
//create a new instance of the target class
object instance = Activator.CreateInstance(interfaceType);
Type type = GenerateInterfaceImplementType(interfaceType, ints[0]);
return Activator.CreateInstance(type, instance);
}
}
public static INTERFACE CreateImplement<INTERFACE>()
where INTERFACE : class
{
return CreateImplement(typeof(INTERFACE)) as INTERFACE;
}
public static object CreateProxy(Type target, InvocationDelegate invocationHandler)
{
return CreateProxy(CreateImplement(target), invocationHandler);
}
public static object CreateProxy(object target, InvocationDelegate invocationHandler)
{
return CreateProxy(target, invocationHandler, false, null);
}
public static object CreateProxy(Type target, InvocationDelegate invocationHandler, bool strict)
{
return CreateProxy(CreateImplement(target), invocationHandler, strict);
}
public static object CreateProxy(object target, InvocationDelegate invocationHandler, bool strict)
{
return CreateProxy(target, invocationHandler, strict, null);
}
public static object CreateProxy(Type target, InvocationDelegate invocationHandler, bool strict, Type[] supportedTypes)
{
return CreateProxy(CreateImplement(target), invocationHandler, strict, supportedTypes);
}
public static object CreateProxy(object target, InvocationDelegate invocationHandler, bool strict, Type[] supportedTypes)
{
return new DynamicProxyImpl(target, invocationHandler, strict, supportedTypes).GetTransparentProxy();
}
public static Type GenerateInterfaceImplementType(Type typeInterface, Type typeImplement)
{
if (null == typeInterface)
{
throw new ArgumentException("The first argument must not be null!");
}
if (typeInterface.IsInterface==false)
{
throw new ArgumentException(typeInterface.FullName + " must be an interface instead of a class");
}
string strTypeName = Interface_DefaultNameSpace+"." + typeInterface.ToString() + "_" + (typeImplement == null ? "Impl" : typeImplement.ToString());
if (Interface_HashTypes.ContainsKey(strTypeName))
{
return Interface_HashTypes[strTypeName];
}
System.Diagnostics.Debug.WriteLine("Create a new implements for >>>>>>>>" + typeInterface.FullName);
lock (Interface_HashTypes)
{
List<PropertyInfo> pisInterface = TypeHelper.GetAllPropertyInfos(typeInterface);
List<MethodInfo> misInterfaceList = TypeHelper.GetAllMethodInfos(typeInterface,false);
List<MethodInfo> misImplex = typeImplement == null ? null : TypeHelper.GetAllMethodInfos(typeImplement,true, BindingFlags.Public | BindingFlags.Instance);
AssemblyName aName = new AssemblyName(Interface_DefaultNameSpace);
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
aName,
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder =
assemblyBuilder.DefineDynamicModule(aName.Name, aName.Name + ".dll",true);
TypeBuilder typeBuilder = moduleBuilder.DefineType(strTypeName,
TypeAttributes.Public, null, new Type[] { typeInterface });
FieldBuilder innerParentObject =
null == typeImplement ?null:
typeBuilder.DefineField(
"internal__wrappedInstance",typeImplement,
FieldAttributes.Private);
ConstructorBuilder ctor1 = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
null == typeImplement ? Type.EmptyTypes : new Type[] { typeImplement });
ILGenerator constructorIL = ctor1.GetILGenerator();
if (null != typeImplement)
{
//父亲构造
constructorIL.Emit(OpCodes.Ldarg_0);
constructorIL.Emit(OpCodes.Call, typeImplement.GetConstructor(Type.EmptyTypes));
//设置私有变量值
constructorIL.Emit(OpCodes.Ldarg_0);
constructorIL.Emit(OpCodes.Ldarg_1);
constructorIL.Emit(OpCodes.Stfld, innerParentObject);
constructorIL.Emit(OpCodes.Ret);
}
else
{
constructorIL.Emit(OpCodes.Ret);
}
foreach (PropertyInfo item in pisInterface)
{
MethodInfo getMi = _FindGetMethodInfo(misImplex, item);
MethodInfo setMi = _FindSetMethodInfo(misImplex, item);
_CreateProperty(typeBuilder, innerParentObject, item, getMi, setMi);
}
foreach (MethodInfo item in misInterfaceList)
{
MethodInfo instanceMi = _FindMethodInfo(misImplex, item);
_CreateMethod(typeBuilder, innerParentObject, item, instanceMi);
}
Type newType = typeBuilder.CreateType();
Interface_HashTypes.Add(strTypeName, newType);
return newType;
}
}
private static MethodInfo _FindSetMethodInfo(List<MethodInfo> miList, PropertyInfo pi)
{
if (null == miList || null == pi)
{
return null;
}
foreach (MethodInfo item in miList)
{
if (item.Name.Equals("set_" + pi.Name) && item.IsSpecialName)
{
return item;
}
}
return null;
}
private static Type GenerateInterfaceImplementType(Type typeInterface)
{
return GenerateInterfaceImplementType(typeInterface, null);
}
private static void _CreateMethod(TypeBuilder typeBuilder, FieldBuilder innerParentObject
, MethodInfo mi, MethodInfo instanceMi)
{
List<Type> paramTyleList = new List<Type>();
foreach (var item in mi.GetParameters())
paramTyleList.Add(item.ParameterType);
MethodBuilder mb = typeBuilder.DefineMethod(
mi.Name,
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
mi.ReturnType,
paramTyleList.ToArray());
ILGenerator il = mb.GetILGenerator();
if (instanceMi == null)
{
il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
il.Emit(OpCodes.Throw);
}
else
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, innerParentObject);
switch (paramTyleList.Count)
{
case 0:
break;
case 1:
il.Emit(OpCodes.Ldarg_1);
break;
case 2:
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
break;
case 3:
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldarg_3);
break;
default:
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldarg_3);
Int32 sCount = Math.Min(paramTyleList.Count, 127);
for (int i = 4; i <= sCount; i++)
{
il.Emit(OpCodes.Ldarg_S, i);
}
for (int i = 128; i <= paramTyleList.Count; i++)
{
il.Emit(OpCodes.Ldarg, i);
}
break;
}
//Invoke the old functionality
il.Emit(OpCodes.Callvirt, instanceMi);
il.Emit(OpCodes.Ret);
}
}
private static void _CreateProperty(TypeBuilder typeBuilder, FieldBuilder innerParentObject
, PropertyInfo pi, MethodInfo getMi, MethodInfo setMi)
{
FieldBuilder privateField = null;
if (null == getMi || null == setMi)
{
privateField = typeBuilder.DefineField("private_____" + pi.Name, pi.PropertyType, FieldAttributes.Private);
}
String name = pi.Name;
Type type = pi.PropertyType;
PropertyBuilder pb = typeBuilder.DefineProperty(
name,
PropertyAttributes.HasDefault,
type,
null);
MethodAttributes getSetAttr = MethodAttributes.Public
| MethodAttributes.SpecialName
| MethodAttributes.HideBySig
| MethodAttributes.NewSlot
| MethodAttributes.Virtual
| MethodAttributes.Final;
MethodBuilder mbGetAccessor = typeBuilder.DefineMethod(
"get_" + name,
getSetAttr,
type,
Type.EmptyTypes);
{
ILGenerator getIL = mbGetAccessor.GetILGenerator();
if (getMi != null)
{
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, innerParentObject);
getIL.Emit(OpCodes.Callvirt, getMi);
getIL.Emit(OpCodes.Ret);
}
else
{
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, privateField);
getIL.Emit(OpCodes.Ret);
}
}
MethodBuilder mbSetAccessor = typeBuilder.DefineMethod(
"set_" + name,
getSetAttr,
null,
new Type[] { type });
{
ILGenerator setIL = mbSetAccessor.GetILGenerator();
if (setMi != null)
{
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldfld, innerParentObject);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Callvirt, setMi);
setIL.Emit(OpCodes.Ret);
}
else
{
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, privateField);
setIL.Emit(OpCodes.Ret);
}
}
if (pi.CanRead)
{
pb.SetGetMethod(mbGetAccessor);
}
if (pi.CanWrite)
{
pb.SetSetMethod(mbSetAccessor);
}
}
private static MethodInfo _FindGetMethodInfo(List<MethodInfo> miList, PropertyInfo pi)
{
if (null == miList || null == pi)
{
return null;
}
foreach (MethodInfo item in miList)
{
if (item.Name.Equals("get_" + pi.Name) && item.IsSpecialName)
{
return item;
}
}
return null;
}
private static MethodInfo _FindMethodInfo(List<MethodInfo> miList, MethodInfo mi)
{
if (null == miList || null == mi)
{
return null;
}
foreach (var item in miList)
{
if (_MethodInfoEqual(item, mi)) return item;
}
return null;
}
private static Boolean _MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)
{
if (mi1.IsSpecialName == true || mi2.IsSpecialName == true) return false;
if (mi1.Name != mi2.Name) return false;
if (mi1.ReturnType != mi2.ReturnType) return false;
ParameterInfo[] pis1 = mi1.GetParameters();
ParameterInfo[] pis2 = mi2.GetParameters();
if (pis1.Length != pis2.Length) return false;
for (int i = 0; i < pis1.Length; i++)
{
ParameterInfo pi1 = pis1[i];
ParameterInfo pi2 = pis2[i];
if (pi1.ParameterType != pi2.ParameterType) return false;
}
return true;
}
#endregion Methods
}
public class DynamicProxyImpl :
System.Runtime.Remoting.Proxies.RealProxy
, IDynamicProxy
, System.Runtime.Remoting.IRemotingTypeInfo
{
#region Fields
private InvocationDelegate invocationHandler;
private object proxyTarget;
private bool strict;
private Type[] supportedTypes;
#endregion Fields
#region Constructors
protected internal DynamicProxyImpl(object proxyTarget
, InvocationDelegate invocationHandler
, bool strict
, Type[] supportedTypes)
: base(typeof(IDynamicProxy))
{
this.proxyTarget = proxyTarget;
this.invocationHandler = invocationHandler;
this.strict = strict;
this.supportedTypes = supportedTypes;
}
#endregion Constructors
#region Properties
public InvocationDelegate InvocationHandler
{
get { return invocationHandler; }
set { invocationHandler = value; }
}
public object ProxyTarget
{
get { return proxyTarget; }
set { proxyTarget = value; }
}
public bool Strict
{
get { return strict; }
set { strict = value; }
}
public Type[] SupportedTypes
{
get { return supportedTypes; }
set { supportedTypes = value; }
}
public string TypeName
{
get { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
set { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
}
#endregion Properties
#region Methods
public bool CanCastTo(System.Type toType, object obj)
{
// Assume we can (which is the default unless strict is true)
bool canCast = true;
if (strict)
{
// First check if the proxyTarget supports the cast
if (toType.IsAssignableFrom(proxyTarget.GetType()))
{
canCast = true;
}
else if (supportedTypes != null)
{
canCast = false;
// Check if the list of supported interfaces supports the cast
foreach (Type type in supportedTypes)
{
if (toType == type)
{
canCast = true;
break;
}
}
}
else
{
canCast = false;
}
}
return canCast;
}
public override System.Runtime.Remoting.ObjRef CreateObjRef(System.Type type)
{
throw new NotSupportedException("ObjRef for DynamicProxy isn't supported");
}
public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage message)
{
// Convert to a MethodCallMessage
System.Runtime.Remoting.Messaging.IMethodCallMessage methodMessage = new System.Runtime.Remoting.Messaging.MethodCallMessageWrapper((System.Runtime.Remoting.Messaging.IMethodCallMessage)message);
// Extract the method being called
System.Reflection.MethodBase method = methodMessage.MethodBase;
// Perform the call
object returnValue = null;
if (method.DeclaringType == typeof(IDynamicProxy))
{
// Handle IDynamicProxy interface calls on this instance instead of on the proxy target instance
returnValue = method.Invoke(this, methodMessage.Args);
}
else
{
// Delegate to the invocation handler
returnValue = invocationHandler(proxyTarget, method, methodMessage.Args);
}
// Create the return message (ReturnMessage)
System.Runtime.Remoting.Messaging.ReturnMessage returnMessage = new System.Runtime.Remoting.Messaging.ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
return returnMessage;
}
#endregion Methods
}