Mercurial > pub > bltoolkit
diff Extensions/JointureAddOn/Emit/DynamicCompilationSpike.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Extensions/JointureAddOn/Emit/DynamicCompilationSpike.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,129 @@ +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace BLToolkit.Emit +{ + public delegate object GetHandler(object source); + + public delegate void SetHandler(object source, object value); + + public delegate object InstantiateObjectHandler(); + + public static class DynamicMethodCompiler + { + // DynamicMethodCompiler + + // CreateInstantiateObjectDelegate + internal static InstantiateObjectHandler CreateInstantiateObjectHandler(Type type) + { + ConstructorInfo constructorInfo = + type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, + new Type[0], null); + if (constructorInfo == null) + { + throw new ApplicationException( + string.Format( + "The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).", + type)); + } + + var dynamicMethod = new DynamicMethod("InstantiateObject", MethodAttributes.Static | MethodAttributes.Public, + CallingConventions.Standard, typeof(object), null, type, true); + ILGenerator generator = dynamicMethod.GetILGenerator(); + generator.Emit(OpCodes.Newobj, constructorInfo); + generator.Emit(OpCodes.Ret); + return (InstantiateObjectHandler)dynamicMethod.CreateDelegate(typeof(InstantiateObjectHandler)); + } + + // CreateGetDelegate + internal static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo) + { + MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true); + DynamicMethod dynamicGet = CreateGetDynamicMethod(type); + ILGenerator getGenerator = dynamicGet.GetILGenerator(); + + getGenerator.Emit(OpCodes.Ldarg_0); + getGenerator.Emit(OpCodes.Call, getMethodInfo); + BoxIfNeeded(getMethodInfo.ReturnType, getGenerator); + getGenerator.Emit(OpCodes.Ret); + + return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler)); + } + + // CreateGetDelegate + internal static GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo) + { + DynamicMethod dynamicGet = CreateGetDynamicMethod(type); + ILGenerator getGenerator = dynamicGet.GetILGenerator(); + + getGenerator.Emit(OpCodes.Ldarg_0); + getGenerator.Emit(OpCodes.Ldfld, fieldInfo); + BoxIfNeeded(fieldInfo.FieldType, getGenerator); + getGenerator.Emit(OpCodes.Ret); + + return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler)); + } + + // CreateSetDelegate + internal static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo) + { + MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true); + DynamicMethod dynamicSet = CreateSetDynamicMethod(type); + ILGenerator setGenerator = dynamicSet.GetILGenerator(); + + setGenerator.Emit(OpCodes.Ldarg_0); + setGenerator.Emit(OpCodes.Ldarg_1); + UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator); + setGenerator.Emit(OpCodes.Call, setMethodInfo); + setGenerator.Emit(OpCodes.Ret); + + return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler)); + } + + // CreateSetDelegate + internal static SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo) + { + DynamicMethod dynamicSet = CreateSetDynamicMethod(type); + ILGenerator setGenerator = dynamicSet.GetILGenerator(); + + setGenerator.Emit(OpCodes.Ldarg_0); + setGenerator.Emit(OpCodes.Ldarg_1); + UnboxIfNeeded(fieldInfo.FieldType, setGenerator); + setGenerator.Emit(OpCodes.Stfld, fieldInfo); + setGenerator.Emit(OpCodes.Ret); + + return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler)); + } + + // CreateGetDynamicMethod + private static DynamicMethod CreateGetDynamicMethod(Type type) + { + return new DynamicMethod("DynamicGet", typeof(object), new[] { typeof(object) }, type, true); + } + + // CreateSetDynamicMethod + private static DynamicMethod CreateSetDynamicMethod(Type type) + { + return new DynamicMethod("DynamicSet", typeof(void), new[] { typeof(object), typeof(object) }, type, true); + } + + // BoxIfNeeded + private static void BoxIfNeeded(Type type, ILGenerator generator) + { + if (type.IsValueType) + { + generator.Emit(OpCodes.Box, type); + } + } + + // UnboxIfNeeded + private static void UnboxIfNeeded(Type type, ILGenerator generator) + { + if (type.IsValueType) + { + generator.Emit(OpCodes.Unbox_Any, type); + } + } + } +} \ No newline at end of file