private unsafe static Type DefineDelegateType(Type[] parameterTypes, Type resultType, bool implDynamicInterfaces) { var delegateBuilder = DynamicAssembly.DefineType( $"{nameof(MethodHelper)}_{nameof(Delegate)}_{Guid.NewGuid().ToString("N")}", TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate)); var ctorBuilder = delegateBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) }); ctorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); var invokeBuilder = delegateBuilder.DefineMethod( InvokeMethodName, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, CallingConventions.Standard, resultType, parameterTypes); invokeBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); if (implDynamicInterfaces) { OverrideDynamicInvokeImpl(delegateBuilder, invokeBuilder, parameterTypes, resultType); ImplInterface(delegateBuilder, invokeBuilder, parameterTypes, resultType); ImplObjectInterface(delegateBuilder, invokeBuilder, parameterTypes, resultType); ImplInstanceDynamicImpl(delegateBuilder, invokeBuilder, parameterTypes, resultType); } return(delegateBuilder.CreateTypeInfo()); }
public static object CreateInstanceByIL <TSource, TDestination>(MethodBase method) { if (!VersionDifferences.IsSupportEmit) { return(null); } return(Activator.CreateInstance(DynamicAssembly.DefineType( $"{typeof(TSource).Name}_To_{typeof(TDestination).Name}_{Guid.NewGuid().ToString("N")}", TypeAttributes.Public | TypeAttributes.Sealed, typeBuilder => { typeBuilder.AddInterfaceImplementation(typeof(IXConverter <TSource, TDestination>)); typeBuilder.DefineMethod( nameof(IXConverter <TSource, TDestination> .Convert), MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.Final, CallingConventions.HasThis, typeof(TDestination), new Type[] { typeof(TSource) }, (methodBuilder, ilGen) => { List <Type> argsTypes = new List <Type>(); Type returnType; // Get args types and return type. { if (method is ConstructorInfo constructor) { returnType = constructor.DeclaringType; } else if (method is MethodInfo methodInfo) { if (!method.IsStatic) { var thisType = methodInfo.DeclaringType;; if (thisType.IsValueType) { thisType = thisType.MakeByRefType(); } argsTypes.Add(thisType); } returnType = methodInfo.ReturnType; } else { throw new NotSupportedException(nameof(method)); } foreach (var item in method.GetParameters()) { argsTypes.Add(item.ParameterType); } } // Load args { foreach (var item in argsTypes) { // 如果需要 Type 参数,可以认为它需要的是目标的类型信息。 if (item == typeof(Type)) { ilGen.LoadType(typeof(TDestination)); } else if (item == typeof(TSource)) { ilGen.LoadArgument(1); } else if (item == typeof(TSource).MakeByRefType()) { ilGen.LoadArgumentAddress(1); } else if (typeof(TSource).IsValueType && item.IsAssignableFrom(typeof(TSource))) { ilGen.LoadArgument(1); ilGen.Box(typeof(TSource)); } else if (item.IsAssignableFrom(typeof(TSource))) { ilGen.LoadArgument(1); } else { throw new NotSupportedException(nameof(method)); } } } // Call { if (method is ConstructorInfo constructor) { ilGen.NewObject(constructor); } else { ilGen.Call(method); } } // Return { if (returnType.IsByRef) { returnType = returnType.GetElementType(); ilGen.LoadValue(returnType); } if (returnType.IsValueType && returnType != typeof(TDestination)) { if (typeof(TDestination).IsAssignableFrom(returnType)) { // Box ilGen.Box(typeof(TDestination)); } else { var convertMethod = typeof(XConvert <TDestination>).GetMethod(nameof(XConvert <TDestination> .Convert)); convertMethod = convertMethod.MakeGenericMethod(returnType); ilGen.Call(convertMethod); } } } ilGen.Return(); }); }))); }
protected override IntPtr InternalGetStaticsBasePointer(StaticsBaseBlock statics_base_block) { if (get_statics_base_pointer_func == null) { var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); FieldInfo gc_static_field_info = null; FieldInfo non_gc_static_field_info = null; FieldInfo thread_gc_static_field_info = null; FieldInfo thread_non_gc_static_field_info = null; foreach (var item in fields) { if (item.IsLiteral) { continue; } switch (TypeHelper.GetStaticBaseBlock(item)) { case StaticsBaseBlock.GC: gc_static_field_info ??= item; break; case StaticsBaseBlock.NonGC: non_gc_static_field_info ??= item; break; case StaticsBaseBlock.ThreadGC: thread_gc_static_field_info ??= item; break; case StaticsBaseBlock.ThreadNonGC: thread_non_gc_static_field_info ??= item; break; } } if (gc_static_field_info == null && non_gc_static_field_info == null && thread_gc_static_field_info == null && thread_non_gc_static_field_info == null) { return(IntPtr.Zero); } get_statics_base_pointer_func = DynamicAssembly.DefineDynamicMethod <GetStaticsBasePointerFunc>((dym, ilGen) => { if (gc_static_field_info != null) { ilGen.LoadArgument(0); ilGen.LoadFieldAddress(gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (non_gc_static_field_info != null) { ilGen.LoadArgument(1); ilGen.LoadFieldAddress(non_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(non_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (thread_gc_static_field_info != null) { ilGen.LoadArgument(2); ilGen.LoadFieldAddress(thread_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(thread_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } if (thread_non_gc_static_field_info != null) { ilGen.LoadArgument(3); ilGen.LoadFieldAddress(thread_non_gc_static_field_info); ilGen.LoadConstant(TypeHelper.OffsetOf(thread_non_gc_static_field_info)); ilGen.Subtract(); ilGen.StoreValue(typeof(IntPtr)); } ilGen.Return(); }, typeof(T).Module, true); } get_statics_base_pointer_func( out var gc_statics_base_pointer, out var non_gc_statics_base_pointer, out var thread_gc_statics_base_pointer, out var thread_non_gc_statics_base_pointer ); return(statics_base_block switch { StaticsBaseBlock.GC => gc_statics_base_pointer, StaticsBaseBlock.NonGC => non_gc_statics_base_pointer, StaticsBaseBlock.ThreadGC => thread_gc_statics_base_pointer, StaticsBaseBlock.ThreadNonGC => thread_non_gc_statics_base_pointer, _ => throw new NotSupportedException(), });
public static void GetAllFieldOffsetByEmit(Type type) { var fields = TypeHelper.GetFields(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); DynamicAssembly.DefineDynamicMethod <Action>((_, ilGen) => { var obj_address = ilGen.DeclareLocal(typeof(IntPtr)); var gc_static_base_address = ilGen.DeclareLocal(typeof(IntPtr)); var non_gc_static_base_address = ilGen.DeclareLocal(typeof(IntPtr)); ilGen.LoadConstant((IntPtr)(-1)); // max ptr ilGen.StoreLocal(gc_static_base_address); ilGen.LoadConstant((IntPtr)(-1)); // max ptr ilGen.StoreLocal(non_gc_static_base_address); /* 分配一个模拟实例 */ ilGen.LoadConstant(8); ilGen.LocalAllocate(); ilGen.StoreLocal(obj_address); foreach (var item in fields) { /* 跳过常量 */ if (item.IsLiteral) { continue; } if (item.IsStatic) { if (item.FieldType.IsValueType) { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(non_gc_static_base_address); ilGen.Call(MethodOf <IntPtr, IntPtr, IntPtr>(Min)); ilGen.StoreLocal(non_gc_static_base_address); } else { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(gc_static_base_address); ilGen.Call(MethodOf <IntPtr, IntPtr, IntPtr>(Min)); ilGen.StoreLocal(gc_static_base_address); } } } foreach (var item in fields) { /* 跳过常量 */ if (item.IsLiteral) { continue; } /* 加载字段 Id */ ilGen.LoadConstant(item.FieldHandle.Value); if (item.IsStatic) { // Offset = Address - Base Address. if (item.FieldType.IsValueType) { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(non_gc_static_base_address); ilGen.Subtract(); } else { ilGen.LoadFieldAddress(item); ilGen.LoadLocal(gc_static_base_address); ilGen.Subtract(); } } else { /* Offset = Address - Instance. */ ilGen.LoadLocal(obj_address); ilGen.LoadFieldAddress(item); ilGen.LoadLocal(obj_address); ilGen.Subtract(); /* if class then Offset -= sizeof TypeHandle. */ if (type.IsClass) { ilGen.LoadConstant(TypeHelper.GetObjectValueByteOffset()); ilGen.Subtract(); } } ilGen.ConvertInt32(); ilGen.Call(MethodOf <IntPtr, int>(Add)); } ilGen.Return(); }, type.Module, true)(); }