#region License
/*
* Copyright 2002-2006 the original author or authors.
*
* 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.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
using Spring.Proxy;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework.DynamicProxy{
/// <summary>
/// Base class for AOP method builders that contains common functionalities.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public abstract class AbstractAopProxyMethodBuilder : AbstractProxyMethodBuilder
{
#region Fields
/// <summary>
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </summary>
protected IAopProxyTypeGenerator aopProxyGenerator;
/// <summary>
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </summary>
protected IDictionary targetMethods;
/// <summary>
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s defined on the proxy.
/// </summary>
protected IDictionary onProxyTargetMethods;
// variables
/// <summary>
/// The local variable to store the list of method interceptors.
/// </summary>
protected LocalBuilder interceptors;
/// <summary>
/// The local variable to store the target type being proxied.
/// </summary>
protected LocalBuilder targetType;
/// <summary>
/// The local variable to store method arguments.
/// </summary>
protected LocalBuilder arguments;
/// <summary>
/// The local variable to store the return value.
/// </summary>
protected LocalBuilder returnValue;
#if NET_2_0
/// <summary>
/// The local variable to store the closed generic method
/// when the target method is generic.
/// </summary>
protected LocalBuilder genericTargetMethod;
/// <summary>
/// The local variable to store the closed generic method
/// when the target method defined on the proxy is generic.
/// </summary>
protected LocalBuilder genericOnProxyTargetMethod;
#endif
/// <summary>
/// The field to cache the target <see cref="System.Reflection.MethodInfo"/>.
/// </summary>
protected FieldBuilder targetMethodCacheField;
/// <summary>
/// The field to cache the target <see cref="System.Reflection.MethodInfo"/>
/// defined on the proxy.
/// </summary>
protected FieldBuilder onProxyTargetMethodCacheField;
// convinience fields
/// <summary>
/// Indicates if the method returns a value.
/// </summary>
protected bool methodReturnsValue;
// private fields
private static IDictionary ldindOpCodes;
#endregion
#region Constructor(s) / Destructor
static AbstractAopProxyMethodBuilder()
{
ldindOpCodes = new Hashtable();
ldindOpCodes[typeof(sbyte)] = OpCodes.Ldind_I1;
ldindOpCodes[typeof(short)] = OpCodes.Ldind_I2;
ldindOpCodes[typeof(int)] = OpCodes.Ldind_I4;
ldindOpCodes[typeof(long)] = OpCodes.Ldind_I8;
ldindOpCodes[typeof(byte)] = OpCodes.Ldind_U1;
ldindOpCodes[typeof(ushort)] = OpCodes.Ldind_U2;
ldindOpCodes[typeof(uint)] = OpCodes.Ldind_U4;
ldindOpCodes[typeof(ulong)] = OpCodes.Ldind_I8;
ldindOpCodes[typeof(float)] = OpCodes.Ldind_R4;
ldindOpCodes[typeof(double)] = OpCodes.Ldind_R8;
ldindOpCodes[typeof(char)] = OpCodes.Ldind_U2;
ldindOpCodes[typeof(bool)] = OpCodes.Ldind_I1;
}
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="explicitImplementation">
/// <see langword="true"/> if the interface is to be
/// implemented explicitly; otherwise <see langword="false"/>.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
protected AbstractAopProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
bool explicitImplementation, IDictionary targetMethods)
: this(typeBuilder, aopProxyGenerator, explicitImplementation, targetMethods, new Hashtable())
{
}
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="explicitImplementation">
/// <see langword="true"/> if the interface is to be
/// implemented explicitly; otherwise <see langword="false"/>.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
/// <param name="onProxyTargetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s defined on the proxy.
/// </param>
protected AbstractAopProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
bool explicitImplementation, IDictionary targetMethods, IDictionary onProxyTargetMethods)
: base(typeBuilder, aopProxyGenerator, explicitImplementation)
{
this.aopProxyGenerator = aopProxyGenerator;
this.targetMethods = targetMethods;
this.onProxyTargetMethods = onProxyTargetMethods;
}
#endregion
#region Protected Members
/// <summary>
/// Generates the proxy method.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void GenerateMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
methodReturnsValue = (method.ReturnType != typeof(void));
DeclareLocals(il, method);
GenerateTargetMethodCacheField(il, method);
GenerateOnProxyTargetMethodCacheField(il, method);
BeginMethod(il, method);
GenerateMethodLogic(il, method, interfaceMethod);
EndMethod(il, method);
}
/// <summary>
/// Generates unique method id for the cache field.
/// </summary>
/// <param name="method">The target method.</param>
/// <returns>An unique method name.</returns>
protected virtual string GenerateMethodCacheFieldId(MethodInfo method)
{
return "_m" + Guid.NewGuid().ToString("N");
}
/// <summary>
/// Create static field that will cache target method.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The target method.</param>
protected virtual void GenerateTargetMethodCacheField(
ILGenerator il, MethodInfo method)
{
string methodId = GenerateMethodCacheFieldId(method);
targetMethods.Add(methodId, method);
targetMethodCacheField = typeBuilder.DefineField(methodId, typeof(MethodInfo),
FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly);
#if NET_2_0
MakeGenericMethod(il, method, targetMethodCacheField, genericTargetMethod);
#endif
}
/// <summary>
/// Create static field that will cache target method when defined on the proxy.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The target method.</param>
protected virtual void GenerateOnProxyTargetMethodCacheField(
ILGenerator il, MethodInfo method)
{
}
#if NET_2_0
/// <summary>
/// Create a closed generic method for the current call
/// if target method is a generic definition.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The target method.</param>
/// <param name="methodCacheField">
/// The field that contains the method generic definition
/// </param>
/// <param name="localMethod">
/// The local variable to store the closed generic method.
/// </param>
protected void MakeGenericMethod(ILGenerator il, MethodInfo method,
FieldBuilder methodCacheField, LocalBuilder localMethod)
{
// if target method is a generic definition,
// create a closed generic method for the current call.
if (method.IsGenericMethodDefinition)
{
Type[] genericArgs = method.GetGenericArguments();
LocalBuilder typeArgs = il.DeclareLocal(typeof(Type[]));
il.Emit(OpCodes.Ldsfld, methodCacheField);
// specify array size and create an array
il.Emit(OpCodes.Ldc_I4, genericArgs.Length);
il.Emit(OpCodes.Newarr, typeof(Type));
il.Emit(OpCodes.Stloc, typeArgs);
// populate array with type arguments
for (int i = 0; i < genericArgs.Length; i++)
{
il.Emit(OpCodes.Ldloc, typeArgs);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldtoken, genericArgs[i]);
il.EmitCall(OpCodes.Call, References.GetTypeFromHandle, null);
il.Emit(OpCodes.Stelem_Ref);
}
il.Emit(OpCodes.Ldloc, typeArgs);
il.Emit(OpCodes.Callvirt, References.MakeGenericMethod);
il.Emit(OpCodes.Stloc, localMethod);
}
}
#endif
/// <summary>
/// Generates the IL instructions that pushes
/// the target type on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected virtual void PushTargetType(ILGenerator il)
{
aopProxyGenerator.PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetTypeField);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected virtual void PushAdvisedProxy(ILGenerator il)
{
aopProxyGenerator.PushAdvisedProxy(il);
}
/// <summary>
/// Pushes the target <see cref="System.Reflection.MethodInfo"/> to stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void PushTargetMethodInfo(ILGenerator il, MethodInfo method)
{
#if NET_2_0
if (method.IsGenericMethodDefinition)
{
il.Emit(OpCodes.Ldloc, genericTargetMethod);
return;
}
#endif
il.Emit(OpCodes.Ldsfld, targetMethodCacheField);
}
/// <summary>
/// Pushes the target <see cref="System.Reflection.MethodInfo"/> defined on the proxy to stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void PushOnProxyTargetMethodInfo(ILGenerator il, MethodInfo method)
{
if (onProxyTargetMethodCacheField != null)
{
#if NET_2_0
if (method.IsGenericMethodDefinition)
{
il.Emit(OpCodes.Ldloc, genericOnProxyTargetMethod);
return;
}
#endif
il.Emit(OpCodes.Ldsfld, onProxyTargetMethodCacheField);
}
else
{
il.Emit(OpCodes.Ldnull);
}
}
/// <summary>
/// Creates local variable declarations.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void DeclareLocals(ILGenerator il, MethodInfo method)
{
interceptors = il.DeclareLocal(typeof(IList));
targetType = il.DeclareLocal(typeof(Type));
arguments = il.DeclareLocal(typeof(Object[]));
#if NET_2_0
if (method.IsGenericMethodDefinition)
{
genericTargetMethod = il.DeclareLocal(typeof(MethodInfo));
genericOnProxyTargetMethod = il.DeclareLocal(typeof(MethodInfo));
}
#endif
if (methodReturnsValue)
{
returnValue = il.DeclareLocal(method.ReturnType);
}
#if DEBUG
interceptors.SetLocalSymInfo("interceptors");
targetType.SetLocalSymInfo("targetType");
arguments.SetLocalSymInfo("arguments");
#if NET_2_0
if (method.IsGenericMethodDefinition)
{
genericTargetMethod.SetLocalSymInfo("genericTargetMethod");
genericOnProxyTargetMethod.SetLocalSymInfo("genericOnProxyTargetMethod");
}
#endif
if (methodReturnsValue)
{
returnValue.SetLocalSymInfo("returnValue");
}
#endif
}
/// <summary>
/// Initializes local variables
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void BeginMethod(ILGenerator il, MethodInfo method)
{
Label jmpProxyNotExposed = il.DefineLabel();
// set current proxy to this object
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.AdvisedField);
il.EmitCall(OpCodes.Callvirt, References.ExposeProxyProperty, null);
il.Emit(OpCodes.Brfalse_S, jmpProxyNotExposed);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, References.PushProxyMethod, null);
il.MarkLabel(jmpProxyNotExposed);
// initialize targetType
PushTargetType(il);
il.Emit(OpCodes.Stloc, targetType);
// initialize interceptors
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldloc, targetType);
PushTargetMethodInfo(il, method);
il.EmitCall(OpCodes.Call, References.GetInterceptorsMethod, null);
il.Emit(OpCodes.Stloc, interceptors);
}
/// <summary>
/// Generates method logic.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected virtual void GenerateMethodLogic(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
Label jmpDirectCall = il.DefineLabel();
Label jmpEndIf = il.DefineLabel();
// check if there are any interceptors
il.Emit(OpCodes.Ldloc, interceptors);
il.EmitCall(OpCodes.Callvirt, References.CountProperty, null);
il.Emit(OpCodes.Ldc_I4_0);
// if not jump to direct call
il.Emit(OpCodes.Ble, jmpDirectCall);
// otherwise call Invoke and jump to method end
CallInvoke(il, method);
il.Emit(OpCodes.Br, jmpEndIf);
// call method directly
il.MarkLabel(jmpDirectCall);
CallDirectProxiedMethod(il, method, interfaceMethod);
if (methodReturnsValue)
{
// store return value, unboxing is not necessary because we called method directly
il.Emit(OpCodes.Stloc, returnValue);
}
il.MarkLabel(jmpEndIf);
if (methodReturnsValue)
{
if (!method.ReturnType.IsValueType)
{
ProcessReturnValue(il, returnValue);
}
}
}
/// <summary>
/// Calls method using Invoke
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void CallInvoke(ILGenerator il, MethodInfo method)
{
ParameterInfo[] parameters = method.GetParameters();
SetupMethodArguments(il, method, parameters);
PushAdvisedProxy(il);
// setup parameters for call
il.Emit(OpCodes.Ldarg_0); // proxy
PushTarget(il); // target
il.Emit(OpCodes.Ldloc, targetType); // target type
PushTargetMethodInfo(il, method); // method
PushOnProxyTargetMethodInfo(il, method); // method defined on proxy
il.Emit(OpCodes.Ldloc, arguments); // args
il.Emit(OpCodes.Ldloc, interceptors); // interceptors
// call Invoke
il.EmitCall(OpCodes.Call, References.InvokeMethod, null);
// process return value
if (methodReturnsValue)
{
EmitUnboxIfNeeded(il, method.ReturnType);
il.Emit(OpCodes.Stloc, returnValue);
}
else
{
il.Emit(OpCodes.Pop);
}
// process byRef arguments
for (int i = 0; i < parameters.Length; i++)
{
if (parameters[i].ParameterType.IsByRef)
{
il.Emit(OpCodes.Ldarg_S, i + 1);
il.Emit(OpCodes.Ldloc, arguments);
il.Emit(OpCodes.Ldc_I4_S, i);
il.Emit(OpCodes.Ldelem_Ref);
Type type = parameters[i].ParameterType.GetElementType();
EmitUnboxIfNeeded(il, type);
EmitStoreValueIndirect(il, type);
}
}
}
/// <summary>
/// Setup proxied method arguments.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="parameters">The method's parameters.</param>
protected void SetupMethodArguments(
ILGenerator il, MethodInfo method, ParameterInfo[] parameters)
{
if (parameters.Length > 0)
{
// specify array size and create an array
il.Emit(OpCodes.Ldc_I4, parameters.Length);
il.Emit(OpCodes.Newarr, typeof(Object));
il.Emit(OpCodes.Stloc, arguments);
// populate array with params
for (int i = 0; i < parameters.Length; i++)
{
Type type = parameters[i].ParameterType;
il.Emit(OpCodes.Ldloc, arguments);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg_S, i + 1);
// setup byRef arguments
if (type.IsByRef)
{
type = type.GetElementType();
EmitLoadValueIndirect(il, type);
}
#if NET_2_0
if (type.IsValueType || type.IsGenericParameter)
#else
if (type.IsValueType)
#endif
{
il.Emit(OpCodes.Box, type);
}
il.Emit(OpCodes.Stelem_Ref);
}
}
else
{
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Stloc, arguments);
}
}
/// <summary>
/// Calls proxied method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected abstract void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod);
/// <summary>
/// Ends method by returning return value if appropriate.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected virtual void EndMethod(ILGenerator il, MethodInfo method)
{
Label jmpProxyNotExposed = il.DefineLabel();
// reset current proxy to old value
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.AdvisedField);
il.EmitCall(OpCodes.Callvirt, References.ExposeProxyProperty, null);
il.Emit(OpCodes.Brfalse_S, jmpProxyNotExposed);
il.EmitCall(OpCodes.Call, References.PopProxyMethod, null);
il.MarkLabel(jmpProxyNotExposed);
if (methodReturnsValue)
{
il.Emit(OpCodes.Ldloc, returnValue);
}
}
#endregion
#region Reflection.Emit utility methods
/// <summary>
/// Emits MSIL instructions to load a value of the specified <paramref name="type"/>
/// onto the evaluation stack indirectly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="type">The type of the value.</param>
protected static void EmitLoadValueIndirect(ILGenerator il, Type type)
{
if (type.IsValueType)
{
if (type == typeof(int)) il.Emit(OpCodes.Ldind_I4);
else if (type == typeof(uint)) il.Emit(OpCodes.Ldind_U4);
else if (type == typeof(char)) il.Emit(OpCodes.Ldind_I2);
else if (type == typeof(bool)) il.Emit(OpCodes.Ldind_I1);
else if (type == typeof(float)) il.Emit(OpCodes.Ldind_R4);
else if (type == typeof(double)) il.Emit(OpCodes.Ldind_R8);
else if (type == typeof(short)) il.Emit(OpCodes.Ldind_I2);
else if (type == typeof(ushort)) il.Emit(OpCodes.Ldind_U2);
else if (type == typeof(long) || type == typeof(ulong)) il.Emit(OpCodes.Ldind_I8);
else il.Emit(OpCodes.Ldobj, type);
}
else
{
il.Emit(OpCodes.Ldind_Ref);
}
}
/// <summary>
/// Emit MSIL instructions to store a value of the specified <paramref name="type"/>
/// at a supplied address.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="type">The type of the value.</param>
protected static void EmitStoreValueIndirect(ILGenerator il, Type type)
{
if (type.IsValueType)
{
if (type.IsEnum) EmitStoreValueIndirect(il, Enum.GetUnderlyingType(type));
else if (type == typeof(int)) il.Emit(OpCodes.Stind_I4);
else if (type == typeof(short)) il.Emit(OpCodes.Stind_I2);
else if (type == typeof(long) || type == typeof(ulong)) il.Emit(OpCodes.Stind_I8);
else if (type == typeof(char)) il.Emit(OpCodes.Stind_I2);
else if (type == typeof(bool)) il.Emit(OpCodes.Stind_I1);
else if (type == typeof(float)) il.Emit(OpCodes.Stind_R4);
else if (type == typeof(double)) il.Emit(OpCodes.Stind_R8);
else il.Emit(OpCodes.Stobj, type);
}
else
{
il.Emit(OpCodes.Stind_Ref);
}
}
/// <summary>
/// Emits MSIL instructions to convert the boxed representation
/// of the supplied <paramref name="type"/> to its unboxed form.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="type">The type specified in the instruction.</param>
protected static void EmitUnboxIfNeeded(ILGenerator il, Type type)
{
#if NET_2_0
if (type.IsValueType || type.IsGenericParameter)
{
il.Emit(OpCodes.Unbox_Any, type);
}
#else
if (type.IsValueType)
{
il.Emit(OpCodes.Unbox, type);
il.Emit(OpCodes.Ldobj, type);
}
#endif
}
#endregion
}
#region References helper class definition
internal struct References
{
// fields
public static readonly FieldInfo AdvisedField =
typeof(AdvisedProxy).GetField("m_advised", BindingFlags.Instance | BindingFlags.Public);
public static readonly FieldInfo TargetTypeField =
typeof(AdvisedProxy).GetField("m_targetType", BindingFlags.Instance | BindingFlags.Public);
public static readonly FieldInfo IntroductionsField =
typeof(AdvisedProxy).GetField("m_introductions", BindingFlags.Instance | BindingFlags.Public);
public static readonly FieldInfo TargetSourceWrapperField =
typeof(AdvisedProxy).GetField("m_targetSourceWrapper", BindingFlags.Instance | BindingFlags.Public);
// constructors
public static readonly ConstructorInfo BaseCompositionAopProxyConstructor =
typeof(BaseCompositionAopProxy).GetConstructor(new Type[] { typeof(IAdvised) });
public static readonly ConstructorInfo BaseCompositionAopProxySerializationConstructor =
typeof(BaseCompositionAopProxy).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
new Type[] {typeof(SerializationInfo), typeof(StreamingContext)},
null);
public static readonly ConstructorInfo AdvisedProxyConstructor =
typeof(AdvisedProxy).GetConstructor(new Type[] { typeof(IAdvised), typeof(IAopProxy) });
public static readonly ConstructorInfo AdvisedProxySerializationConstructor =
typeof(AdvisedProxy).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
new Type[] {typeof (SerializationInfo), typeof (StreamingContext)},
null);
public static readonly ConstructorInfo ObjectConstructor =
typeof(Object).GetConstructor(Type.EmptyTypes);
// methods
public static readonly MethodInfo PushProxyMethod =
typeof(AopContext).GetMethod("PushProxy", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(Object) }, null);
public static readonly MethodInfo PopProxyMethod =
typeof(AopContext).GetMethod("PopProxy", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
public static readonly MethodInfo InvokeMethod =
typeof(AdvisedProxy).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(Object), typeof(Object), typeof(Type), typeof(MethodInfo), typeof(MethodInfo), typeof(Object[]), typeof(IList) }, null);
public static readonly MethodInfo GetInterceptorsMethod =
typeof(AdvisedProxy).GetMethod("GetInterceptors", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(Type), typeof(MethodInfo) }, null);
public static readonly MethodInfo GetTargetMethod =
typeof(ITargetSourceWrapper).GetMethod("GetTarget", Type.EmptyTypes);
public static readonly MethodInfo GetTypeMethod =
typeof(Object).GetMethod("GetType", Type.EmptyTypes);
public static readonly MethodInfo GetTypeFromHandle =
typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
#if NET_2_0
public static readonly MethodInfo MakeGenericMethod =
typeof(MethodInfo).GetMethod("MakeGenericMethod", new Type[] { typeof(Type[]) });
#endif
public static readonly MethodInfo DisposeMethod =
typeof(IDisposable).GetMethod("Dispose", Type.EmptyTypes);
public static readonly MethodInfo AddSerializationValue =
typeof(SerializationInfo).GetMethod("AddValue", new Type[] { typeof(string), typeof(object) });
public static readonly MethodInfo GetSerializationValue =
typeof(SerializationInfo).GetMethod("GetValue", new Type[] { typeof(string), typeof(Type) });
// properties
public static readonly MethodInfo ExposeProxyProperty =
typeof(IAdvised).GetProperty("ExposeProxy", typeof(Boolean)).GetGetMethod();
public static readonly MethodInfo CountProperty =
typeof(ICollection).GetProperty("Count", typeof(Int32)).GetGetMethod();
}
#endregion
}
|