using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Reflection.Emit; namespace Server.Reflection { public static class BasePropertyAccessor { public static InvokeHandler GetPropertyInvoker( Type type, string propertyName ) { MethodInfo mi = type.GetMethod( "get_" + propertyName ); if ( mi == null ) return null; return BaseMethodInvoker.GetMethodInvoker( mi ); } public static InvokeHandler SetPropertyInvoker( Type type, string propertyName ) { PropertyInfo pi = type.GetProperty( propertyName ); if ( pi == null ) return null; MethodInfo mi = type.GetMethod( "set_" + pi.Name ); if ( mi == null ) return null; return GetMethodInvoker4Set( mi ); } public static InvokeHandler GetPropertyInvoker( Type type, PropertyInfo property ) { if ( property == null ) return null; MethodInfo mi = type.GetMethod( "get_" + property.Name ); if ( mi == null ) return null; return BaseMethodInvoker.GetMethodInvoker( mi ); } public static InvokeHandler SetPropertyInvoker( Type type, PropertyInfo property ) { if ( property == null ) return null; MethodInfo mi = type.GetMethod( "set_" + property.Name ); if ( mi == null ) return null; return GetMethodInvoker4Set( mi ); } private static InvokeHandler GetMethodInvoker4Set( MethodInfo methodInfo ) { DynamicMethod dynamicMethod = new DynamicMethod( string.Empty, typeof( object ), new Type[] { typeof( object ), typeof( object[] ) }, methodInfo.DeclaringType.Module ); ILGenerator il = dynamicMethod.GetILGenerator(); ParameterInfo[] ps = methodInfo.GetParameters(); Type[] paramTypes = new Type[ps.Length]; for ( int i = 0; i < paramTypes.Length; i++ ) { if ( ps[i].ParameterType.IsByRef ) paramTypes[i] = ps[i].ParameterType.GetElementType(); else paramTypes[i] = ps[i].ParameterType; } LocalBuilder[] locals = new LocalBuilder[paramTypes.Length]; for ( int i = 0; i < paramTypes.Length; i++ ) locals[i] = il.DeclareLocal( paramTypes[i], true ); for ( int i = 0; i < paramTypes.Length; i++ ) { il.Emit( OpCodes.Ldarg_1 ); EmitFastInt( il, i ); il.Emit( OpCodes.Ldelem_Ref ); EmitCastToReference( il, paramTypes[i] ); il.Emit( OpCodes.Stloc, locals[i] ); } if ( !methodInfo.IsStatic ) il.Emit( OpCodes.Ldarg_0 ); for ( int i = 0; i < paramTypes.Length; i++ ) { if ( ps[i].ParameterType.IsByRef ) il.Emit( OpCodes.Ldloca_S, locals[i] ); else il.Emit( OpCodes.Ldloc, locals[i] ); } if ( methodInfo.IsStatic ) il.EmitCall( OpCodes.Call, methodInfo, null ); else il.EmitCall( OpCodes.Callvirt, methodInfo, null ); if ( methodInfo.ReturnType == typeof( void ) ) il.Emit( OpCodes.Ldnull ); else EmitBoxIfNeeded( il, methodInfo.ReturnType ); for ( int i = 0; i < paramTypes.Length; i++ ) { if ( ps[i].ParameterType.IsByRef ) { il.Emit( OpCodes.Ldarg_1 ); EmitFastInt( il, i ); il.Emit( OpCodes.Ldloc, locals[i] ); if ( locals[i].LocalType.IsValueType ) il.Emit( OpCodes.Box, locals[i].LocalType ); il.Emit( OpCodes.Stelem_Ref ); } } il.Emit( OpCodes.Ret ); InvokeHandler invoder = (InvokeHandler)dynamicMethod.CreateDelegate( typeof( InvokeHandler ) ); return invoder; } private static void EmitCastToReference( ILGenerator il, System.Type type ) { if ( type.IsValueType ) { il.Emit( OpCodes.Unbox_Any, type ); } else { il.Emit( OpCodes.Castclass, type ); } } private static void EmitBoxIfNeeded( ILGenerator il, System.Type type ) { if ( type.IsValueType ) { il.Emit( OpCodes.Box, type ); } } private static void EmitFastInt( ILGenerator il, int value ) { switch ( value ) { case -1: il.Emit( OpCodes.Ldc_I4_M1 ); return; case 0: il.Emit( OpCodes.Ldc_I4_0 ); return; case 1: il.Emit( OpCodes.Ldc_I4_1 ); return; case 2: il.Emit( OpCodes.Ldc_I4_2 ); return; case 3: il.Emit( OpCodes.Ldc_I4_3 ); return; case 4: il.Emit( OpCodes.Ldc_I4_4 ); return; case 5: il.Emit( OpCodes.Ldc_I4_5 ); return; case 6: il.Emit( OpCodes.Ldc_I4_6 ); return; case 7: il.Emit( OpCodes.Ldc_I4_7 ); return; case 8: il.Emit( OpCodes.Ldc_I4_8 ); return; } if ( value > -129 && value < 128 ) { il.Emit( OpCodes.Ldc_I4_S, (SByte)value ); } else { il.Emit( OpCodes.Ldc_I4, value ); } } } }