C# 如何通过反射设置 StructLayoutAttribute.Pack?

标签 c# reflection struct

我正在通过反射动态创建一个 C# 结构,当我在调试器中检查该结构的类型时,我注意到 StructLayoutAttribute.Pack默认为 8。我想将 Pack 设置为 1。

本质上,我想通过反射来完成将此属性添加到结构声明中可以完成的操作:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

我试过在创建类型后使用反射,但由于 StructLayoutAttribute 属性没有 Setter,它会抛出异常。

我的直觉是它需要在调用 ModuleBuilder.DefineType 时发生(我当前正在设置 LayoutKind 等),但我没有看到任何明显的对应 TypeAttribute .

感谢任何指点。此处类的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace AcmeCo.Serializable
{
    public class DynamicSimStructBuilder
    {

        private static Type structType;

        public static object GetStructInstance() {
            object ptInstance = Activator.CreateInstance(GetStruct(), new object[] { });
            return ptInstance;
        }

        public static Type GetStruct() {

            if (structType != null) {
               return structType; 
            }

            AppDomain myDomain = AppDomain.CurrentDomain;
            AssemblyName myAsmName = new AssemblyName("MyDynamicAssembly");

            AssemblyBuilder myAsmBuilder =
               myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder structModule = myAsmBuilder.DefineDynamicModule("StructModule", "MyDynamicAssembly.dll");

            TypeBuilder structTypeBld = structModule.DefineType("AcmeCo.ThirdPartyAPIWrapper.DyanmicStruct", TypeAttributes.Public |
                TypeAttributes.Sealed | TypeAttributes.SequentialLayout | 
                TypeAttributes.Serializable | TypeAttributes.AnsiClass, typeof(ValueType));

            // use a set of variables defined in an XML file to create Fields on the struct
            ThirdPartyAPIVariableCollection collection = ThirdPartyAPIVariableCollection.Deserialize();
            foreach (ThirdPartyAPIVariable variable in collection.ThirdPartyAPIVariables)
            {
                FieldBuilder field = structTypeBld.DefineField(variable.Name, Type.GetType(variable.SystemDataType, true) , FieldAttributes.Public);
            }

            // Base class and base class constructor.
            Type objType = Type.GetType("System.Object");
            ConstructorInfo objCtor = objType.GetConstructor(new Type[] { });

            Type[] ctorParams = { };

            ConstructorBuilder pointCtor =
               structTypeBld.DefineConstructor(MethodAttributes.Public,
                                              CallingConventions.Standard, ctorParams);
            ILGenerator ctorIL = pointCtor.GetILGenerator();

            // Build the constructor. Begin by invoking the base class
            // constructor. The zero-index parameter of the constructor
            // is the new instance. Store the values of the fields.
            ctorIL.Emit(OpCodes.Ldarg_0);
            ctorIL.Emit(OpCodes.Call, objCtor);
            ctorIL.Emit(OpCodes.Ret);


            // Create the type, and then create an instance of the type 
            // (or not, doesn't hurt to comment the CreateInstance line out...)
            Type ptType = structTypeBld.CreateType();

            object ptInstance = Activator.CreateInstance(ptType, new object[] { });

            DynamicSimStructBuilder.structType = ptType;
            int sizeOfNewData = System.Runtime.InteropServices.Marshal.SizeOf(ptType);
            Console.WriteLine("New type is: " + sizeOfNewData);

            // save the newly created type to a DLL for use later
            // (or not, doesn't hurt to comment the next line out...)
            myAsmBuilder.Save("MyDynamicAssembly.dll");

            return ptType;
        }
    }
}

最佳答案

看起来再添加一个参数可以让您指定包装尺寸:

来自 http://msdn.microsoft.com/en-us/library/eyzw8bhy.aspx :

public TypeBuilder DefineType(
    string name,
    TypeAttributes attr,
    Type parent,
    PackingSize packsize
)

关于C# 如何通过反射设置 StructLayoutAttribute.Pack?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16673378/

相关文章:

c++ - 将第二个数组的元素添加到第一个数组的末尾

c# - C# Mongo DB collection.find() 方法不接受过滤器

c# - 缺少引用 OLEDB 连接类型的库

c# - 运行 Docker 时无法识别命令

c# - 为什么我的号码四舍五入不正确?

c# - 找不到类型 'System.Web.HttpPostedFile' 的构造函数

java - 如何使用反射比较类?

c# - 如何在运行时确定 .Net 程序的入口点?

c# - 在 WCF 中使用 DataContract 传递对象

c - 这是一个合适的函数定义吗?