📄 reflectionoptimizer.cs
字号:
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Security;
using System.Security.Permissions;
using NHibernate.Properties;
using NHibernate.Util;
namespace NHibernate.Bytecode.Lightweight
{
public class ReflectionOptimizer : IReflectionOptimizer, IInstantiationOptimizer
{
private IAccessOptimizer accessOptimizer;
private CreateInstanceInvoker createInstanceMethod;
public IAccessOptimizer AccessOptimizer
{
get { return accessOptimizer; }
}
public IInstantiationOptimizer InstantiationOptimizer
{
get { return this; }
}
public object CreateInstance()
{
return createInstanceMethod();
}
private System.Type mappedType;
private System.Type typeOfThis;
/// <summary>
/// Class constructor.
/// </summary>
public ReflectionOptimizer(
System.Type mappedType, IGetter[] getters, ISetter[] setters)
{
// save off references
this.mappedType = mappedType;
this.typeOfThis = mappedType.IsValueType ? mappedType.MakeByRefType() : mappedType;
//this.getters = getters;
//this.setters = setters;
GetPropertyValuesInvoker getInvoker = GenerateGetPropertyValuesMethod(getters);
SetPropertyValuesInvoker setInvoker = GenerateSetPropertyValuesMethod(getters, setters);
this.accessOptimizer = new AccessOptimizer(
getInvoker,
setInvoker,
getters,
setters);
this.createInstanceMethod = CreateCreateInstanceMethod(mappedType);
}
/// <summary>
/// Generates a dynamic method which creates a new instance of <paramref name="type" />
/// when invoked.
/// </summary>
private CreateInstanceInvoker CreateCreateInstanceMethod(System.Type type)
{
if (type.IsInterface || type.IsAbstract)
{
return null;
}
DynamicMethod method = new DynamicMethod(string.Empty, typeof(object), null, type, true);
ILGenerator il = method.GetILGenerator();
if (type.IsValueType)
{
LocalBuilder tmpLocal = il.DeclareLocal(type);
il.Emit(OpCodes.Ldloca, tmpLocal);
il.Emit(OpCodes.Initobj, type);
il.Emit(OpCodes.Ldloc, tmpLocal);
il.Emit(OpCodes.Box, type);
}
else
{
ConstructorInfo constructor = ReflectHelper.GetDefaultConstructor(type);
if (constructor == null)
{
throw new InstantiationException("Object class " + type + " must declare a default (no-argument) constructor", type);
}
il.Emit(OpCodes.Newobj, constructor);
}
il.Emit(OpCodes.Ret);
return (CreateInstanceInvoker)method.CreateDelegate(typeof(CreateInstanceInvoker));
}
protected DynamicMethod CreateDynamicMethod(System.Type returnType, System.Type[] argumentTypes)
{
System.Type owner = mappedType.IsInterface ? typeof(object) : mappedType;
bool canSkipChecks = SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
return new DynamicMethod(string.Empty, returnType, argumentTypes, owner, canSkipChecks);
}
private static void EmitCastToReference(ILGenerator il, System.Type type)
{
if (type.IsValueType)
{
il.Emit(OpCodes.Unbox, type);
}
else
{
il.Emit(OpCodes.Castclass, type);
}
}
/// <summary>
/// Generates a dynamic method on the given type.
/// </summary>
private GetPropertyValuesInvoker GenerateGetPropertyValuesMethod(IGetter[] getters)
{
System.Type[] methodArguments = new System.Type[] { typeof(object), typeof(GetterCallback) };
DynamicMethod method = CreateDynamicMethod(typeof(object[]), methodArguments);
ILGenerator il = method.GetILGenerator();
LocalBuilder thisLocal = il.DeclareLocal(typeOfThis);
LocalBuilder dataLocal = il.DeclareLocal(typeof(object[]));
// Cast the 'this' pointer to the appropriate type and store it in a local variable
il.Emit(OpCodes.Ldarg_0);
EmitCastToReference(il, mappedType);
il.Emit(OpCodes.Stloc, thisLocal);
// Allocate the values array and store it in a local variable
il.Emit(OpCodes.Ldc_I4, getters.Length);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc, dataLocal);
//get all the data from the object into the data array to be returned
for (int i = 0; i < getters.Length; i++)
{
// get the member accessors
IGetter getter = getters[i];
// queue up the array storage location for the value
il.Emit(OpCodes.Ldloc, dataLocal);
il.Emit(OpCodes.Ldc_I4, i);
// get the value...
IOptimizableGetter optimizableGetter = getter as IOptimizableGetter;
if (optimizableGetter != null)
{
// using the getter's emitted IL code
il.Emit(OpCodes.Ldloc, thisLocal);
optimizableGetter.Emit(il);
EmitUtil.EmitBoxIfNeeded(il, getter.ReturnType);
}
else
{
// using the getter itself via a callback
MethodInfo invokeMethod =
typeof(GetterCallback).GetMethod(
"Invoke", new System.Type[] { typeof(object), typeof(int) });
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Callvirt, invokeMethod);
}
//store the value
il.Emit(OpCodes.Stelem_Ref);
}
// Return the data array
il.Emit(OpCodes.Ldloc, dataLocal.LocalIndex);
il.Emit(OpCodes.Ret);
return (GetPropertyValuesInvoker)method.CreateDelegate(typeof(GetPropertyValuesInvoker));
}
/// <summary>
/// Generates a dynamic method on the given type.
/// </summary>
/// <returns></returns>
private SetPropertyValuesInvoker GenerateSetPropertyValuesMethod(IGetter[] getters, ISetter[] setters)
{
System.Type[] methodArguments = new System.Type[] { typeof(object), typeof(object[]), typeof(SetterCallback) };
DynamicMethod method = CreateDynamicMethod(null, methodArguments);
ILGenerator il = method.GetILGenerator();
// Declare a local variable used to store the object reference (typed)
LocalBuilder thisLocal = il.DeclareLocal(typeOfThis);
il.Emit(OpCodes.Ldarg_0);
EmitCastToReference(il, mappedType);
il.Emit(OpCodes.Stloc, thisLocal.LocalIndex);
for (int i = 0; i < setters.Length; i++)
{
// get the member accessor
ISetter setter = setters[i];
System.Type valueType = getters[i].ReturnType;
IOptimizableSetter optimizableSetter = setter as IOptimizableSetter;
if (optimizableSetter != null)
{
// load 'this'
il.Emit(OpCodes.Ldloc, thisLocal);
// load the value from the data array
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
EmitUtil.PreparePropertyForSet(il, valueType);
// using the setter's emitted IL
optimizableSetter.Emit(il);
}
else
{
// using the setter itself via a callback
MethodInfo invokeMethod =
typeof(SetterCallback).GetMethod(
"Invoke", new System.Type[] { typeof(object), typeof(int), typeof(object) });
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, i);
// load the value from the data array
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem_Ref);
il.Emit(OpCodes.Callvirt, invokeMethod);
}
}
// Setup the return
il.Emit(OpCodes.Ret);
return (SetPropertyValuesInvoker)method.CreateDelegate(typeof(SetPropertyValuesInvoker));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -