如何在C#中创建具有动态属性和属性的结构

时间:2013-02-26 10:44:47

标签: c# c++ reflection pinvoke

在我的应用程序中,需要使用P / Invoke将绝对任意的对象/结构传递给C ++函数。根据因特网,任何对象都可以作为C ++结构传递(它们在调用期间被固定到特定的存储器位置)。由于我只对数据感兴趣并且不打算调用任何方法,因此这足以满足我的需求。但是,实验表明这些对象必须具有[StructLayout(LayoutKind.Sequential)]属性,否则代码将无法编译。不幸的是,这些类是由其他开发人员创建的,并不保证具有此属性。

要解决此问题,一种解决方案是将对象传递给特殊的C#包装函数,该函数将:

  1. 使用Type.GetProperties
  2. 检索对象的属性
  3. 动态创建具有必要属性的结构,并从对象复制值。
  4. 添加[StructLayout(LayoutKind.Sequential)]属性。
  5. 将此结构与第1步中检索到的元数据一起传递给C ++(以便C ++知道对象结构是什么以及如何阅读它)
  6. 由于我是C#的新手,我不确定如何动态创建具有任意属性和属性的结构。到目前为止我发现的是MakeGenericTypeExpandoObject,但是需要的是创建一个先前未在任何地方定义的动态结构 - 甚至不是通用对象。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

这样的事情能为你效劳吗?

    [StructLayout(LayoutKind.Sequential)]
    struct MyStruct
    {
        public int Size;
        public IntPtr PtrToArrayOfMetadata;
        public IntPtr PtrToArrayOfObjects;
    }

    public enum Type
    {
        Int, 
        Float,
        Decimal
    }

然后发送一个“动态”对象

        Type[] metadata = new Type[2];
        metadata[0] = Type.Int;
        metadata[1] = Type.Float;

        object[] obj = new object[2];
        obj[0] = 2;
        obj[1]= 1;

        GCHandle objHandle = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection);
        IntPtr ptrObj = GCHandle.ToIntPtr(objHandle);

        objHandle = GCHandle.Alloc(metadata, GCHandleType.WeakTrackResurrection);
        IntPtr ptrMeta = GCHandle.ToIntPtr(objHandle);

        MyStruct tmp = new MyStruct();
        tmp.Size = 2;
        tmp.PtrToArrayOfMetadata = ptrMeta;
        tmp.PtrToArrayOfObjects = ptrObj;