生成一个结构在运行时基于字符串中定义的数据类型 [英] Generating a struct at run-time based on data types defined in a string

查看:168
本文介绍了生成一个结构在运行时基于字符串中定义的数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何能产生一个结构在运行时从类型字符串中定义的序列?

How can I generate a struct at run-time from a sequence of types defined in a string?

我有一个标头,例如包括浮球,浮球,字节[255]。 我有如下这个头,并保持数据序列的二进制数据。 我不知道这个数据类型,直到我读在运行时的标题,我想生成,我可以用编组二进制数据转化为结构的数组的结构体。

I have a header that e.g. contains "float, float, byte[255]". I have binary data that follows this header and keeps the data in sequence. I don't know the data type until I read the header at run-time, and I would like to generate a struct that I can used to Marshal the binary data into an array of structs.

任何想法?

推荐答案

显然,你知道你的应用程序的要求,但作为lejon规定的问题是如何访问结构,一旦你创建它。在C#中,你将不得不赴汤蹈火,而不是vb的,你并不需要显式声明的类型。

Obviously you know what the requirements of your application are, but as lejon stated the problem is how to access the struct once you create it. In c# you will have to jump through hoops, as opposed to vb where you don't need to explicitly declare types.

我能想到的几种方法来完成你想要的。你可以使用codeDOM产生的code,请参阅本 HTTP:// WWW。 15seconds.com/issue/020917.htm

I can think of several ways to accomplish what you want. You could use CodeDom to generate your code, see this http://www.15seconds.com/issue/020917.htm

亲自为一个简单的结构体,我会constuct的code mandually

Personally for a simply struct, I would constuct the code mandually

  string szCode =@"using System;
  using System.Windows.Forms;

  namespace RunTimeCompile
  {
      [StructLayoutAttribute(LayoutKind.Sequential)]
      public string MyStruct
      {"

然后在你的头文件中的每个数据类型添加成员到SZ code字符串。 (你需要建立一个基本的功能来分析你的类型本):

Then for each data type in your head file append the member to the szCode String. (You'll need to build a basic function to parse your types this):

szCode += "float Field1;\n"; 
szCode += "float Field2;\n"; 
szCode += "byte[255] Field3;\n";

和关闭了你的code ...

and close off your code...

szeCode+=";\n;\n";

现在,你有源$ C ​​$ C使用codeDOM进行编译。

now that you have the source code use CodeDom to compile it.

oCodeDomProvider = CodeDomProvider.CreateProvider("CSharp");
// Add what referenced assemblies
CompilerParameters oCompilerParameters = new CompilerParameters();
oCompilerParameters.ReferencedAssemblies.Add("system.dll");
// set the compiler to create a DLL
oCompilerParameters.GenerateExecutable = false;
// set the dll to be created in memory and not on the hard drive
oCompilerParameters.GenerateInMemory = true;
oCompilerResults =
  oCodeDomProvider.CompileAssemblyFromSource(oCompilerParameters, szCode);

请注意:您也可以从一个文件编译为使用CompileAssemblyFromFile反对在存储源$ C ​​$ C

Note: You could also compile from a file as opposed to in memory source code using CompileAssemblyFromFile

现在继续检查之前没有编译错误

Now before continuing check there are no compilation errors

if (oCompilerResults.Errors.Count!=0) return; // add you own error handling

现在你可以检索像这样动态生成的结构的实例

now you can retrieve an instance of the dynamically generated struct like this

oAssembly = oCompilerResults.CompiledAssembly;
oObject = oAssembly.CreateInstance("RunTimeCompile.MyStruct");
oType = oObject.GetType();

现在你可以看到所有的二进制文件,其中元帅的行成MYSTRUCT [使用元帅或任何其他方法你想序列化的二进制数据(二进制序列也许)]数组。

Now you can read all of the rows of your binary file and Marshal them into an array of MyStruct[] using Marshal or any other method your would like to serialize the binary data (binary serializer perhaps).

例如使用Runtime.Interop.Marshal你可以做这样的事情(你需要这个拨弄了一下,特别是你不能声明MYSTRUCT []在code,所以你需要做的事情像oObjectArray = oAssembly.CreateInstance(RunTimeCompile.MyStruct [])申报destValues​​结果数组):

For example using Runtime.Interop.Marshal you could do something like this (you'll need to fiddle with this a bit, specifically you can't declare MyStruct[] in your code so you need to do something like oObjectArray = oAssembly.CreateInstance("RunTimeCompile.MyStruct[]") to declare the destValues result array):

byte[] sourceData = ReadSourceData(); // TODO: generate method to load your BLOB
MyStruct[] destValues = new MyStruct[Marshal.SizeOf(oType) + 1]
int arrayIndex = 0;

GCHandle handle = GCHandle.Alloc(sourceData, GCHandleType.Pinned);
try
{
IntPtr buffer = handle.AddrOfPinnedObject();
buffer = (IntPtr)(buffer.ToInt32() +
(arrayIndex*Marshal.SizeOf(typeof(MyStruct))));
destStruct = (MyStruct)Marshal.PtrToStructure(buffer, typeof(MyStruct));
}
finally
{
handle.Free();
}

 return MyStruct;

现在你有你的结构数组。

Now you have your array of struct.

这篇关于生成一个结构在运行时基于字符串中定义的数据类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆