基于字符串中定义的数据类型在运行时生成结构

如何在运行时从字符串中定义的一系列类型生成结构?

我有一个标题,例如包含“float,float,byte [255]”。 我有这个标题后面的二进制数据,并按顺序保存数据。 在运行时读取头文件之前我不知道数据类型,我想生成一个结构,我可以用来将二进制数据编组成一个结构数组。

有任何想法吗?

显然你知道你的应用程序的要求是什么,但是当lejon声明问题是如何在创建它时访问该结构。 在c#中,你将不得不跳过箍,而不是你不需要显式声明类型的vb。

我可以想出几种方法来实现你想要的。 您可以使用CodeDom生成代码,请参阅http://www.15seconds.com/issue/020917.htm

就个人简单的结构而言,我会按顺序构造代码

string szCode =@"using System; using System.Windows.Forms; namespace RunTimeCompile { [StructLayoutAttribute(LayoutKind.Sequential)] public string MyStruct {" 

然后,对于头文件中的每种数据类型,将成员附加到szCode String。 (你需要构建一个基本函数来解析你的类型):

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

并关闭你的代码……

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

既然你有源代码使用CodeDom来编译它。

 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从文件进行编译,而不是使用内存源代码进行编译

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

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

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

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

现在,您可以读取二进制文件的所有行,并使用Marshal或您希望序列化二进制数据的任何其他方法(也许是二进制序列化程序)将它们编组为MyStruct []数组。

例如,使用Runtime.Interop.Marshal,您可以执行类似的操作(您需要稍微调整一下,特别是您不能在代码中声明MyStruct [],因此您需要执行类似oObjectArray = oAssembly.CreateInstance的操作。 (“RunTimeCompile.MyStruct []”)声明destValues结果数组):

 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; 

现在你有了你的struct数组。

问题是,一旦你定义了你的结构,你将如何访问它? 您无法静态引用它,因为该类型仅适用于运行时。 您可能必须使用reflection,委托或dynamic 。 有没有更好的方法来做你想要的(比如,一个接受字节数组并根据需要解释它的类)而不是在运行时生成结构?