Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于字符串中定义的数据类型在运行时生成结构_C#_.net - Fatal编程技术网

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

C# 基于字符串中定义的数据类型在运行时生成结构,c#,.net,C#,.net,如何在运行时从字符串中定义的类型序列生成结构 我有一个标题,例如包含“float,float,byte[255]”。 我在这个标题后面有二进制数据,并按顺序保存数据。 在运行时读取头文件之前,我不知道数据类型,我想生成一个结构,用于将二进制数据封送到结构数组中 有什么想法吗?问题是,一旦定义了结构,您将如何访问它?您不能静态引用它,因为该类型仅限于运行时。您必须使用反射、委托或动态。有没有更好的方法来做你想做的事情(比如,一个单独的类接受字节数组并根据需要解释它)而不是在运行时生成一个结构?显然

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

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


有什么想法吗?

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

显然,你知道你的应用程序的要求是什么,但正如lejon所说,问题是一旦创建了结构,如何访问它。在c#中,您必须跳转,而vb则不需要显式声明类型

我可以想出几种方法来实现你的愿望。您可以使用CodeDom生成代码,请参见

就个人而言,对于一个简单的结构,我会强制构造代码

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

  namespace RunTimeCompile
  {
      [StructLayoutAttribute(LayoutKind.Sequential)]
      public string MyStruct
      {"
然后,对于头文件中的每个数据类型,将成员附加到szCode字符串中。(您需要构建一个基本函数来解析您的类型):

关闭你的代码

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);
注意:您也可以使用CompileAseMblyFromFile从文件编译,而不是从内存中的源代码编译

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

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结果数组):


现在您有了结构数组。

无论您在哪里使用该结构,都必须使用反射,确定没有更好的方法吗?似乎“在运行时生成结构”是建议的解决方案。。。您试图解决的真正问题是什么?如何解决,或者学习其他方法。您可以查看Expando对象,看看它是否有帮助:问题是,我必须迭代整个数据集,并单独解析每个数据类型。结构方式只需在内存中放入大量数据,并在其上应用解释“过滤器”。但一旦创建了结构,您将如何访问它?我不知道。通过反射创建“新”结构?如果我在运行时之前知道结构,但在编译时之后,我是否可以在执行时以某种方式将结构源动态编译到.exe中?您可以编写结构遵循的接口,然后创建实现该接口的结构。问题是结构的任何使用都会被装箱(因为接口是引用类型),动态创建结构将非常复杂。您最好编写一个单独的类来解释二进制数据,或者编写一个类的继承树来帮助您。我会考虑这个问题。谢谢
oAssembly = oCompilerResults.CompiledAssembly;
oObject = oAssembly.CreateInstance("RunTimeCompile.MyStruct");
oType = oObject.GetType();
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;