From fbdf46d4938db02d666bbadef48b0fc7254db5b0 Mon Sep 17 00:00:00 2001 From: ravenal Date: Thu, 15 Jul 2010 18:57:45 +0000 Subject: [PATCH] Added Server.Reflection for new Property, Method and Field for setting and getting or invoking methods for more speed. --- Scripts/Reflection/BaseFieldAccessor.cs | 66 +++++++ Scripts/Reflection/BaseMethodInvoker.cs | 151 ++++++++++++++++ Scripts/Reflection/BasePropertyAccessor.cs | 194 +++++++++++++++++++++ Scripts/Reflection/FieldAccessor.cs | 53 ++++++ Scripts/Reflection/Global.cs | 16 ++ Scripts/Reflection/MethodInvoker.cs | 62 +++++++ Scripts/Reflection/PropertyAccesor.cs | 66 +++++++ 7 files changed, 608 insertions(+) create mode 100644 Scripts/Reflection/BaseFieldAccessor.cs create mode 100644 Scripts/Reflection/BaseMethodInvoker.cs create mode 100644 Scripts/Reflection/BasePropertyAccessor.cs create mode 100644 Scripts/Reflection/FieldAccessor.cs create mode 100644 Scripts/Reflection/Global.cs create mode 100644 Scripts/Reflection/MethodInvoker.cs create mode 100644 Scripts/Reflection/PropertyAccesor.cs diff --git a/Scripts/Reflection/BaseFieldAccessor.cs b/Scripts/Reflection/BaseFieldAccessor.cs new file mode 100644 index 000000000..79753d5d9 --- /dev/null +++ b/Scripts/Reflection/BaseFieldAccessor.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection.Emit; +using System.Reflection; + +namespace Server.Reflection +{ + public static class BaseFieldAccessor + { + public static FieldSetInvokeHandler SetFieldInvoker( Type type, string fieldName ) + { + FieldInfo field = type.GetField( fieldName ); + + if ( field == null ) + return null; + + return SetFieldInvoker( type, field ); + } + + public static FieldGetInvokeHandler GetFieldInvoker( Type type, string fieldName ) + { + FieldInfo field = type.GetField( fieldName ); + + if ( field == null ) + return null; + + return GetFieldInvoker( type, field ); + } + + public static FieldSetInvokeHandler SetFieldInvoker( Type t, FieldInfo field ) + { + DynamicMethod dm = new DynamicMethod( "Set" + field.Name, null, new Type[] { t, typeof( V ) }, t ); + ILGenerator il = dm.GetILGenerator(); + + // Load the instance of the object (argument 0) onto the stack + il.Emit( OpCodes.Ldarg_0 ); + il.Emit( OpCodes.Ldarg_1 ); + + // Load the value of the object's field (fi) onto the stack + il.Emit( OpCodes.Stfld, field ); + + // return the value on the top of the stack + il.Emit( OpCodes.Ret ); + + return (FieldSetInvokeHandler)dm.CreateDelegate( typeof( FieldSetInvokeHandler ) ); + } + + public static FieldGetInvokeHandler GetFieldInvoker( Type t, FieldInfo field ) + { + // Member is a Field... + + DynamicMethod dm = new DynamicMethod( "Get" + field.Name, typeof( V ), new Type[] { t }, t ); + ILGenerator il = dm.GetILGenerator(); + + // Load the instance of the object (argument 0) onto the stack + il.Emit( OpCodes.Ldarg_0 ); + // Load the value of the object's field (fi) onto the stack + il.Emit( OpCodes.Ldfld, field ); + // return the value on the top of the stack + il.Emit( OpCodes.Ret ); + + return (FieldGetInvokeHandler)dm.CreateDelegate( typeof( FieldGetInvokeHandler ) ); + } + } +} diff --git a/Scripts/Reflection/BaseMethodInvoker.cs b/Scripts/Reflection/BaseMethodInvoker.cs new file mode 100644 index 000000000..3ca348427 --- /dev/null +++ b/Scripts/Reflection/BaseMethodInvoker.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Reflection.Emit; + +namespace Server.Reflection +{ + public static class BaseMethodInvoker + { + public static InvokeHandler GetMethodInvoker( MethodInfo method ) + { + DynamicMethod dynamicMethod = new DynamicMethod( string.Empty, + typeof( object ), new Type[] { typeof( object ), typeof( object[] ) }, method.DeclaringType.Module ); + + ILGenerator il = dynamicMethod.GetILGenerator(); + ParameterInfo[] ps = method.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 ( !method.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 ( method.IsStatic ) + il.EmitCall( OpCodes.Call, method, null ); + else + il.EmitCall( OpCodes.Callvirt, method, null ); + + if ( method.ReturnType == typeof( void ) ) + il.Emit( OpCodes.Ldnull ); + else + EmitBoxIfNeeded( il, method.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; + } + + public static InvokeHandler GetMethodInvoker( Type type, string methodName ) + { + MethodInfo methodInfo = type.GetMethod( methodName ); + return GetMethodInvoker( methodInfo ); + } + + 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 ); + } + } + } +} diff --git a/Scripts/Reflection/BasePropertyAccessor.cs b/Scripts/Reflection/BasePropertyAccessor.cs new file mode 100644 index 000000000..22f1f4ac9 --- /dev/null +++ b/Scripts/Reflection/BasePropertyAccessor.cs @@ -0,0 +1,194 @@ +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 ); + } + } + } +} diff --git a/Scripts/Reflection/FieldAccessor.cs b/Scripts/Reflection/FieldAccessor.cs new file mode 100644 index 000000000..9ea2d688a --- /dev/null +++ b/Scripts/Reflection/FieldAccessor.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +namespace Server.Reflection +{ + public sealed class FieldAccessor + { + private Type m_Type; + private FieldInfo m_Field; + private bool m_FieldEmpty; + + public Type Type { get { return m_Type; } } + public FieldInfo Field { get { return m_Field; } } + public bool IsFieldEmpty { get { return m_FieldEmpty; } } + + private FieldGetInvokeHandler m_GetMethodHandler; + private FieldSetInvokeHandler m_SetMethodHandler; + + public FieldAccessor( Type type, FieldInfo field ) + { + m_Type = type; + m_Field = field; + + if ( field == null ) + { + m_FieldEmpty = true; + return; + } + + m_FieldEmpty = false; + m_GetMethodHandler = BaseFieldAccessor.GetFieldInvoker( m_Type, field ); + m_SetMethodHandler = BaseFieldAccessor.SetFieldInvoker( m_Type, field ); + } + + public V GetValue( object target ) + { + if ( m_FieldEmpty ) + return default( V ); + + return m_GetMethodHandler( target ); + } + + public void SetValue( object target, V value ) + { + if ( m_FieldEmpty ) + return; + + m_SetMethodHandler( target, value ); + } + } +} diff --git a/Scripts/Reflection/Global.cs b/Scripts/Reflection/Global.cs new file mode 100644 index 000000000..35d95faa1 --- /dev/null +++ b/Scripts/Reflection/Global.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +namespace Server.Reflection +{ + public delegate object InvokeHandler( object target, params object[] paramters ); + + public delegate T InvokeHandler( object target, params object[] paramters ); + + public delegate V FieldGetInvokeHandler( object target ); + + public delegate void FieldSetInvokeHandler( object target, V value ); + +} diff --git a/Scripts/Reflection/MethodInvoker.cs b/Scripts/Reflection/MethodInvoker.cs new file mode 100644 index 000000000..edfb15603 --- /dev/null +++ b/Scripts/Reflection/MethodInvoker.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +namespace Server.Reflection +{ + public sealed class MethodInvoker + { + private MethodInfo m_Method; + private bool m_MethodEmpty; + + public MethodInfo Method { get { return m_Method; } } + public bool IsMethodEmpty { get { return m_MethodEmpty; } } + + private InvokeHandler m_MethodHandler; + + public MethodInvoker( Type type, string methodname ) + { + MethodInfo mi = type.GetMethod( methodname ); + + if ( mi != null ) + m_MethodHandler = BaseMethodInvoker.GetMethodInvoker( mi ); + + m_MethodEmpty = (mi == null) | (m_MethodHandler == null); + } + + public MethodInvoker( MethodInfo method ) + { + m_Method = method; + + if ( method != null ) + m_MethodHandler = BaseMethodInvoker.GetMethodInvoker( method ); + + m_MethodEmpty = (method == null) | (m_MethodHandler == null); + } + + public object Invoke( object target, params object[] parameters ) + { + if ( m_MethodEmpty ) + return null; + + return m_MethodHandler.Invoke( target, parameters ); + } + + public IAsyncResult BeginInvoke( object target, object[] parameters, AsyncCallback callback, object obj ) + { + if ( m_MethodEmpty ) + return null; + + return m_MethodHandler.BeginInvoke( target, parameters, callback, obj ); + } + + public object EndInvoke( IAsyncResult asyncResult ) + { + if ( m_MethodEmpty ) + return null; + + return m_MethodHandler.EndInvoke( asyncResult ); + } + } +} diff --git a/Scripts/Reflection/PropertyAccesor.cs b/Scripts/Reflection/PropertyAccesor.cs new file mode 100644 index 000000000..697d7822c --- /dev/null +++ b/Scripts/Reflection/PropertyAccesor.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +namespace Server.Reflection +{ + public sealed class PropertyAccessor + { + private Type m_Type; + private PropertyInfo m_Property; + private bool m_PropertyEmpty; + + public Type Type { get { return m_Type; } } + public PropertyInfo PropertyInfo { get { return m_Property; } } + public bool IsPropertyEmpty { get { return m_PropertyEmpty; } } + + private InvokeHandler m_GetMethodHandler; + private InvokeHandler m_SetMethodHandler; + + public PropertyAccessor( Type type, string propertyName ) + { + m_Type = type; + + m_GetMethodHandler = BasePropertyAccessor.GetPropertyInvoker( m_Type, propertyName ); + m_SetMethodHandler = BasePropertyAccessor.SetPropertyInvoker( m_Type, propertyName ); + + if ( m_GetMethodHandler == null || m_SetMethodHandler == null ) + m_PropertyEmpty = true; + } + + public PropertyAccessor( Type type, PropertyInfo property ) + { + m_Type = type; + m_Property = property; + + if ( property == null ) + { + m_PropertyEmpty = true; + return; + } + + m_GetMethodHandler = BasePropertyAccessor.GetPropertyInvoker( m_Type, property ); + m_SetMethodHandler = BasePropertyAccessor.SetPropertyInvoker( m_Type, property ); + + if ( m_GetMethodHandler == null || m_SetMethodHandler == null ) + m_PropertyEmpty = true; + } + + public object GetValue( object target, params object[] parameters ) + { + if ( m_PropertyEmpty ) + return null; + + return m_GetMethodHandler( target, parameters ); + } + + public void SetValue( object target, params object[] parameters ) + { + if ( m_PropertyEmpty ) + return; + + m_SetMethodHandler( target, parameters ); + } + } +}