Exemplo n.º 1
0
        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());
        }
Exemplo n.º 2
0
        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();
                });
            })));
        }
Exemplo n.º 3
0
            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(),
                });
Exemplo n.º 4
0
        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)();
        }