例如NHibernate,使用Emit讀取/設置實體屬性時,生成的DynamicMethod每次讀取/設置全部的屬性值,讀取時返回一個object[],設置時提供一個包含各個屬性值的object[]數組。在SELECT時使用這種方式一次設置好所有屬性;在INSERT、UPDATE時則一次讀出全部屬性;在DELETE時則可以直接使用反射從實體上讀取identity屬性,因為從應用層面總體來看反射的性能還是比較好的。
Emit跟反射的性能測試對比如下:
Emit、Reflection代碼:
//A delegate for the dynamic method
public delegate object GetPropertyValueInvoker(object obj);
public class EmitTest
{
private static GetPropertyValueInvoker GetEmitInvoker(Type type, string propertyName)
{
PropertyInfo propInfo = type.GetProperty(propertyName
, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
//Create a DynamicMethod
Type ownerType = type.IsInterface ? typeof(object) : type;
bool canSkipChecks = SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
DynamicMethod method = new DynamicMethod(string.Empty, typeof(object)
, new Type[] { typeof(object) }, ownerType, canSkipChecks);
//Use ILGenerator to build the method body’s IL code
ILGenerator il = method.GetILGenerator();
//Load the first argument of the method call onto stack
il.Emit(OpCodes.Ldarg_0);
//Necessary type conversion
if (type.IsValueType)
il.Emit(OpCodes.Unbox, type);
else [Page]
il.Emit(OpCodes.Castclass, type);
//Call the property’s get method
il.EmitCall(OpCodes.Callvirt, propInfo.GetGetMethod(true), null);
//If getter return a value type, box it to object
if (propInfo.PropertyType.IsValueType)
{
il.Emit(OpCodes.Box, propInfo.PropertyType);
}
//Return the value of the property
il.Emit(OpCodes.Ret);
//Create a delegate for the client to call the dynamic method
GetPropertyValueInvoker getInvoker =
(GetPropertyValueInvoker)method.CreateDelegate(typeof(GetPropertyValueInvoker));
return getInvoker;
}
//simply cache the dynamic method for the type TestEntity
private static IDictionary<string, GetPropertyValueInvoker> _invokerCache
= new Dictionary<string, GetPropertyValueInvoker>(3);
//Use the dynamic method, which is generated by using Emit every time, to get the property’s value
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/