⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reflectionoptimizer.cs

📁 NHibernate NET开发者所需的
💻 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 + -