子类中的唯一结构(C#)
我正在开发一个应用程序,从输入中生成二进制blob。由于二进制blob有很多类型,我想定义一个名为Config的父类,然后定义多个子类。父类将有一个生成二进制blob的方法,每个子类都有一个定义blob格式的唯一结构 家长:子类中的唯一结构(C#),c#,inheritance,reflection,struct,C#,Inheritance,Reflection,Struct,我正在开发一个应用程序,从输入中生成二进制blob。由于二进制blob有很多类型,我想定义一个名为Config的父类,然后定义多个子类。父类将有一个生成二进制blob的方法,每个子类都有一个定义blob格式的唯一结构 家长: class Config { public struct BinaryFormat { public UInt16 _config_length; } // compile parameters to binary form
class Config
{
public struct BinaryFormat
{
public UInt16 _config_length;
}
// compile parameters to binary format
public byte[] CompileToBinary()
{
// find the binary format struct
??????
foreach (var field in typeof(BinaryFormat).GetFields(BindingFlags.Instance | BindingFlags.Public))
{
string identifier = field.Name;
if (identifier == "_config_length")
continue;
ConfigParameter param = FindParameterByIdentifier(identifier);
if (param == null)
throw new Exception("Struct field with no matching parameter (" + identifier + ")");
field.SetValue(null, param.value);
}
int size = Marshal.SizeOf(cfg);
cfg._config_length = (UInt16)size;
byte[] buffer = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(cfg, ptr, true);
Marshal.Copy(ptr, buffer, 0, size);
Marshal.FreeHGlobal(ptr);
return buffer;
}
}
class Config
{
public dynamic binary_struct;
// compile parameters to binary format
public byte[] CompileToBinary()
{
FieldInfo[] fieldinfo = Type.GetType(GetType().FullName + "+BinaryFormat").GetFields(BindingFlags.Instance | BindingFlags.Public);
dynamic cfg = binary_struct;
foreach (var field in fieldinfo)
{
string identifier = field.Name;
if (identifier == "_config_length")
continue;
ConfigParameter param = FindParameterByIdentifier(identifier);
if (param == null)
throw new Exception("Struct field with no matching parameter (" + identifier + ")");
field.SetValue(cfg, Convert.ChangeType(param.value, field.FieldType));
}
int size = Marshal.SizeOf(cfg);
cfg._config_length = (UInt16)size;
byte[] buffer = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(cfg, ptr, true);
Marshal.Copy(ptr, buffer, 0, size);
Marshal.FreeHGlobal(ptr);
return buffer;
}
}
儿童:
class ChildConfig : Config
{
[StructLayout(LayoutKind.Sequential)]
public struct BinaryFormat
{
public UInt16 _config_length;
public sbyte config1;
public sbyte config2;
public sbyte config3;
}
}
class ChildConfig : Config
{
public cfgSettings()
{
binary_struct = new BinaryFormat();
}
[StructLayout(LayoutKind.Sequential)]
private struct BinaryFormat
{
public UInt16 _config_length;
public sbyte Config1;
public sbyte Config2;
public sbyte Config3;
}
}
在CompileToBinary()
中,如果我刚刚创建了一个BinaryFormat类型的新变量,它将使用父类中的结构。如何使用子类中的结构
还是这完全是错误的做法
解决方案,基于m.rogalski的提示和代码 家长:
class Config
{
public struct BinaryFormat
{
public UInt16 _config_length;
}
// compile parameters to binary format
public byte[] CompileToBinary()
{
// find the binary format struct
??????
foreach (var field in typeof(BinaryFormat).GetFields(BindingFlags.Instance | BindingFlags.Public))
{
string identifier = field.Name;
if (identifier == "_config_length")
continue;
ConfigParameter param = FindParameterByIdentifier(identifier);
if (param == null)
throw new Exception("Struct field with no matching parameter (" + identifier + ")");
field.SetValue(null, param.value);
}
int size = Marshal.SizeOf(cfg);
cfg._config_length = (UInt16)size;
byte[] buffer = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(cfg, ptr, true);
Marshal.Copy(ptr, buffer, 0, size);
Marshal.FreeHGlobal(ptr);
return buffer;
}
}
class Config
{
public dynamic binary_struct;
// compile parameters to binary format
public byte[] CompileToBinary()
{
FieldInfo[] fieldinfo = Type.GetType(GetType().FullName + "+BinaryFormat").GetFields(BindingFlags.Instance | BindingFlags.Public);
dynamic cfg = binary_struct;
foreach (var field in fieldinfo)
{
string identifier = field.Name;
if (identifier == "_config_length")
continue;
ConfigParameter param = FindParameterByIdentifier(identifier);
if (param == null)
throw new Exception("Struct field with no matching parameter (" + identifier + ")");
field.SetValue(cfg, Convert.ChangeType(param.value, field.FieldType));
}
int size = Marshal.SizeOf(cfg);
cfg._config_length = (UInt16)size;
byte[] buffer = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(cfg, ptr, true);
Marshal.Copy(ptr, buffer, 0, size);
Marshal.FreeHGlobal(ptr);
return buffer;
}
}
儿童:
class ChildConfig : Config
{
[StructLayout(LayoutKind.Sequential)]
public struct BinaryFormat
{
public UInt16 _config_length;
public sbyte config1;
public sbyte config2;
public sbyte config3;
}
}
class ChildConfig : Config
{
public cfgSettings()
{
binary_struct = new BinaryFormat();
}
[StructLayout(LayoutKind.Sequential)]
private struct BinaryFormat
{
public UInt16 _config_length;
public sbyte Config1;
public sbyte Config2;
public sbyte Config3;
}
}
使用虚拟/重写或抽象/重写方法 定义一个依赖于
BinayFormat
作为参数或使用受保护变量的方法。然后在子类中实现它。这样,只能从具有子类的BinayFormat
类型的子类访问该功能
但这有一个缺点,您将无法访问父结构类型。您是否会使用父结构类型?如果您想互换使用它们,您可能希望它们都依赖于一个公共接口。使用虚拟/重写或抽象/重写方法 定义一个依赖于
BinayFormat
作为参数或使用受保护变量的方法。然后在子类中实现它。这样,只能从具有子类的BinayFormat
类型的子类访问该功能
但这有一个缺点,您将无法访问父结构类型。您是否会使用父结构类型?如果您想互换使用它们,您可能希望它们都依赖于一个公共接口。因此,首先您的
ChildConfig
类将抛出关于隐藏成员某物的非常恼人的警告
class ChildConfig : Config
{
[StructLayout(LayoutKind.Sequential)]
public new struct BinaryFormat // now it wont
{
public UInt16 _config_length;
public sbyte config1;
public sbyte config2;
public sbyte config3;
}
}
第二件事是,在C#中,可以通过指定类型的“路径”来获取类型:
namespace.class.insideclass+inside_结构
但最好的是,大多数方法都被调用到“最顶层”对象,因此,例如,如果从Config
调用GetType()
,它将返回Config
的classType
,但如果从ChildConfig
调用,它将返回ChildConfig
的classType
(才华横溢……)
知道你应该考虑重建你的逻辑有点:
// this was originaly
//foreach (var field in typeof(BinaryFormat).GetFields(BindingFlags.Instance | BindingFlags.Public))
// this should work with every BinaryFormat you want
foreach (var field in Type.GetType(GetType().FullName + "+BinaryFormat").GetFields(BindingFlags.Instance | BindingFlags.Public))
要创建实例,可以在基本Config
对象中添加方法:
public object CreateInstance()
{
return Activator.CreateInstance(Type.GetType(GetType().FullName + "+BinaryFormat"));
}
然后在派生类中使用它:
class ChildConfig : Config
{
private BinaryFormat _format = (BinaryFormat)CreateInstance();
}
因此,首先,您的
ChildConfig
类将抛出关于隐藏成员内容的非常恼人的警告
class ChildConfig : Config
{
[StructLayout(LayoutKind.Sequential)]
public new struct BinaryFormat // now it wont
{
public UInt16 _config_length;
public sbyte config1;
public sbyte config2;
public sbyte config3;
}
}
第二件事是,在C#中,可以通过指定类型的“路径”来获取类型:
namespace.class.insideclass+inside_结构
但最好的是,大多数方法都被调用到“最顶层”对象,因此,例如,如果从Config
调用GetType()
,它将返回Config
的classType
,但如果从ChildConfig
调用,它将返回ChildConfig
的classType
(才华横溢……)
知道你应该考虑重建你的逻辑有点:
// this was originaly
//foreach (var field in typeof(BinaryFormat).GetFields(BindingFlags.Instance | BindingFlags.Public))
// this should work with every BinaryFormat you want
foreach (var field in Type.GetType(GetType().FullName + "+BinaryFormat").GetFields(BindingFlags.Instance | BindingFlags.Public))
要创建实例,可以在基本Config
对象中添加方法:
public object CreateInstance()
{
return Activator.CreateInstance(Type.GetType(GetType().FullName + "+BinaryFormat"));
}
然后在派生类中使用它:
class ChildConfig : Config
{
private BinaryFormat _format = (BinaryFormat)CreateInstance();
}
而不是
typeof(BinaryFormat)
尝试Type.GetType(GetType.FullName+“.BinaryFormat”)
这将调用调用方对象的GetType()
方法,并检索父对象中声明的BinaryFormat
对象,而不是typeof(BinaryFormat)
尝试Type.GetType(GetType.FullName+“.BinaryFormat”)
这将调用调用方对象的GetType()
方法,并检索父对象中声明的BinaryFormat
对象。谢谢,这非常有帮助。不过,我仍然需要创建结构的实例,我很难做到这一点。我尝试了dynamic cfg=(配置)Activator.CreateInstance(GetType().FullName,GetType().FullName+“.BinaryFormat”).Unwrap();
但是我得到了一个无法加载文件或程序集'ConfigGen.ChildConfig'或其依赖项之一的异常。谢谢,这非常有用。不过我仍然需要创建该结构的实例,但我很难做到这一点。我尝试了dynamic cfg=(Config)Activator.CreateInstance(GetType().FullName,GetType()).FullName+“.BinaryFormat”).Unwrap()
但是我得到了一个无法加载文件或程序集'ConfigGen.ChildConfig'或其依赖项之一的异常。我正在考虑将父类中的方法设为静态,并只传递一个对子类的引用。然后,也许可以向子类添加一个可选方法,父类中的静态代码可以使用反射查找。似乎是一种迂回的方法。我正在考虑将父类中的方法设置为静态,并只传递一个对子类的引用。然后,可能会向子类添加一个可选方法,父类中的静态代码可以使用反射来查找。似乎是一种迂回的方法。