c# - 根据字符串中定义的数据类型在运行时生成结构

标签 c# .net

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

我有一个标题,例如包含“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/

相关文章:

.NET - 从用作网络摄像机的 Windows 手机获取视频流

c# - 无法将 lambda 表达式转换为类型 'bool' 因为它不是委托(delegate)类型?

c# - 如何使用数据注释为 WPF 中的文本框创建输入验证?

c# - 初始化数组时出现 StackOverflow 异常

c# - 我可以将异步放在 C# 的顶层(服务层)吗?

c# - 使用 MVVM 如何从许多可视组件或选项更新标签?

c# - SQL Server to .Net Decimals with EF6 database first issue

c# - 需要一些指导来使用 C# 制作 GUI 计算器吗?

c# - 如何检索上传到 Amazon S3 的图片的 url

c# - Google Calendar v3 - 获取所有有权访问日历的用户