简体   繁体   English

子类中的唯一结构(C#)

[英]Unique structs in child classes (C#)

I am developing an app that generates binary blobs from its input. 我正在开发一个从其输入生成二进制blob的应用程序。 As there are many types binary blob, I want to define a parent class called Config, and then multiple child classes. 由于二进制blob有很多类型,我想定义一个名为Config的父类,然后定义多个子类。 The parent class will have a method that generates the binary blob, with each child class having a unique struct that defines the format of the blob. 父类将有一个生成二进制blob的方法,每个子类都有一个唯一的结构,用于定义blob的格式。

Parent: 家长:

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;
    }
}

Child: 儿童:

class ChildConfig : Config
{
    [StructLayout(LayoutKind.Sequential)]
    public struct BinaryFormat
    {
        public UInt16 _config_length;

        public sbyte config1;
        public sbyte config2;
        public sbyte config3;
    }
}

In CompileToBinary() if I just create a new variable of type BinaryFormat it uses the struct from the parent class. CompileToBinary()如果我只是创建一个BinaryFormat类型的新变量,它将使用父类中的结构。 How can I use the struct from the child class? 如何使用子类中的结构?

Or is this entirely the wrong way to go about this? 或者这完全是错误的方法吗?


Solution, based on hints and code from m.rogalski. 解决方案,基于m.rogalski的提示和代码。

Parent: 家长:

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;
    }
}

Child: 儿童:

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;
    }
}

Use virtual/override or abstract/override method 使用virtual / override或abstract / override方法

Define a method which depends on the BinayFormat either as a parameter or use the protected variable. 定义一个依赖于BinayFormat方法作为参数或使用受保护的变量。 Then implement it in the child class. 然后在子类中实现它。 This way the functionality will be accessed only from the child class with the child's BinayFormat type. 这样,只能从具有子类的BinayFormat类型的子类访问该功能。

But this has a downside, you wont be able to access the parent struct type. 但这有一个缺点,你将无法访问父结构类型。 Will you ever use the parent struct type? 你会使用父结构类型吗? If you want to use them interchangeably you might want both of them depend on an common interface. 如果要交替使用它们,您可能希望它们都依赖于通用接口。

So first of all your ChildConfig class will throw very annoying warning about hiding member something... 首先,你的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;
    }
}

Second thing is that in C# you can get type by specifying it's "path": 第二件事是在C#中你可以通过指定它的“路径”来获取类型:

namespace.class.insideclass+inside_structure

But the best thing is that most of the methods are invoked in to "top-most" object so for example if you call GetType() from Config it will return Config 's class Type but if called from ChildConfig it will return ChildConfig 's class Type ( brilliant as ... ). 但最好的是大多数方法被调用到“最顶层”对象中,例如,如果从Config调用GetType() ,它将返回Config的类Type但是如果从ChildConfig调用它将返回ChildConfig的class Type (辉煌为...)。

Knowing thease things you should consider rebuilding your logic a bit: 知道这些事情你应该考虑重建你的逻辑:

// 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))

To create an instance you can add method inside the base Config object : 要创建实例,可以在基本Config对象中添加方法:

public object CreateInstance()
{
    return Activator.CreateInstance(Type.GetType(GetType().FullName + "+BinaryFormat"));
}

And then use it inside your derived classes: 然后在派生类中使用它:

class ChildConfig : Config
{
    private BinaryFormat _format = (BinaryFormat)CreateInstance();
}

Check it out here 在这里查看

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM