如何在运行时从字符串中定义的一系列类型生成结构?
我有一个标题,例如包含“float, float, byte[255]”。 我有跟在这个标题后面的二进制数据,并保持数据的顺序。 在运行时读取 header 之前,我不知道数据类型,并且我想生成一个结构,我可以使用该结构将二进制数据编码为结构数组。
有什么想法吗?
最佳答案
显然您知道您的应用程序的要求是什么,但正如 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 字符串。 (您需要构建一个基本函数来解析您的类型):
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;
现在你有了结构数组。
关于c# - 根据字符串中定义的数据类型在运行时生成结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4991990/