C#继承设计模式问题

C#继承设计模式问题,c#,design-patterns,inheritance,static,C#,Design Patterns,Inheritance,Static,我用不同的格式和长度存储数据。我有一个类层次结构来表示: abstract class BaseDataFormat{ abstract void InitalizeFromBytes(byte [] ); } class DataFormat1 : BaseDataFormat{...} // data stored in 3 bytes class DataFormat2 : BaseDataFormat{...} /// data stored in 4 bytes 当我读

我用不同的格式和长度存储数据。我有一个类层次结构来表示:

abstract class BaseDataFormat{ 
    abstract void InitalizeFromBytes(byte [] );
}

class DataFormat1 : BaseDataFormat{...}  // data stored in 3 bytes
class DataFormat2 : BaseDataFormat{...} /// data stored in 4 bytes
当我读取数据(比如从字节[])时,我需要知道长度(#字节),以便正确地读取和创建相应的类型。DataFormat1和DataFormat2具有不同的长度,因此如何在运行时获取此信息?即

Fcn<DATAFORMATTYPE>(...)
 where DATAFORMATTYPE: BaseDataFormat, new();
{

DATAFORMATTYPE tmp = new DATAFORMATTYPE();
tmp.InitalizeFromBytes(ReadFromByteBuffer( ... someLength));

}
Fcn(…)
其中DATAFORMATTYPE:BaseDataFormat,new();
{
DATAFORMATTYPE tmp=新的DATAFORMATTYPE();
initializeFromBytes(ReadFromByteBuffer(…someLength));
}
如何根据DATAFORMATTYPE对要读取的适当字节进行编码?每个类的长度感觉应该是数据格式类型的静态属性,但是静态属性不能被派生类覆盖,所以我不确定如何做到这一点

可以将长度编码为实例属性,但似乎应该在类级别(即静态)对其进行知识编码。有没有一种设计模式可以解决这个问题


谢谢

如果您真的想强制执行它是类的属性而不是实例的属性,最好是在类上使用属性

但您需要从中构建缓存,因为反射比直接访问慢得多

[AttributeUsage(AttributeTargets.Class)]
class ByteCountAttribute : Attribute
{
    public int Value { get; private set; }
    public ByteCountAttribute(int count)
    {
        Value = count;
    }
}

[ByteCount(5)]
class DataFormat1 : BaseDataFormat{}  // data stored in 3 bytes
[ByteCount(6)]
class DataFormat2 : BaseDataFormat{} /// data stored in 4 bytes

static Dictionary<Type, int> s_typeCache = new Dictionary<Type,int>();
public static int GetByteCount<T>() where T : BaseDataFormat
{
    int result;
    var type = typeof(T);
    if (!s_typeCache.TryGetValue(type, out result))
    {
        var atts = type.GetCustomAttributes(typeof(ByteCountAttribute), false);
        result = ((ByteCountAttribute)atts[0]).Value;
        s_typeCache.Add(type, result);
    }
    return result;
}
[AttributeUsage(AttributeTargets.Class)]
类ByteCountAttribute:属性
{
公共int值{get;private set;}
公共字节计数属性(整数计数)
{
数值=计数;
}
}
[字节计数(5)]
类DataFormat1:BaseDataFormat{}//以3字节存储的数据
[字节计数(6)]
类DataFormat2:BaseDataFormat{}///以4字节存储的数据
静态字典s_typeCache=新字典();
公共静态int GetByteCount(),其中T:BaseDataFormat
{
int结果;
var类型=类型(T);
如果(!s_typeCache.TryGetValue(类型,输出结果))
{
var atts=type.GetCustomAttributes(typeof(ByteCountAttribute),false);
结果=((字节计数属性)atts[0])值;
s_typeCache.Add(类型、结果);
}
返回结果;
}
(代码没有错误管理,但可以正常工作)


正如Darkasasassin93所说,这种方法的一个问题是,您无法强制执行它的存在,因此您必须记录该属性是必需的,与编译器为您执行任务的抽象属性相反。

如果您真的想强制执行它是类的属性,而不是实例将在类上使用属性

但您需要从中构建缓存,因为反射比直接访问慢得多

[AttributeUsage(AttributeTargets.Class)]
class ByteCountAttribute : Attribute
{
    public int Value { get; private set; }
    public ByteCountAttribute(int count)
    {
        Value = count;
    }
}

[ByteCount(5)]
class DataFormat1 : BaseDataFormat{}  // data stored in 3 bytes
[ByteCount(6)]
class DataFormat2 : BaseDataFormat{} /// data stored in 4 bytes

static Dictionary<Type, int> s_typeCache = new Dictionary<Type,int>();
public static int GetByteCount<T>() where T : BaseDataFormat
{
    int result;
    var type = typeof(T);
    if (!s_typeCache.TryGetValue(type, out result))
    {
        var atts = type.GetCustomAttributes(typeof(ByteCountAttribute), false);
        result = ((ByteCountAttribute)atts[0]).Value;
        s_typeCache.Add(type, result);
    }
    return result;
}
[AttributeUsage(AttributeTargets.Class)]
类ByteCountAttribute:属性
{
公共int值{get;private set;}
公共字节计数属性(整数计数)
{
数值=计数;
}
}
[字节计数(5)]
类DataFormat1:BaseDataFormat{}//以3字节存储的数据
[字节计数(6)]
类DataFormat2:BaseDataFormat{}///以4字节存储的数据
静态字典s_typeCache=新字典();
公共静态int GetByteCount(),其中T:BaseDataFormat
{
int结果;
var类型=类型(T);
如果(!s_typeCache.TryGetValue(类型,输出结果))
{
var atts=type.GetCustomAttributes(typeof(ByteCountAttribute),false);
结果=((字节计数属性)atts[0])值;
s_typeCache.Add(类型、结果);
}
返回结果;
}
(代码没有错误管理,但可以正常工作)


正如Darkassassinsin93所说,这种方法的一个问题是,您无法强制它的存在,因此您必须记录该属性是必需的,与编译器为您执行任务的抽象属性相反。

可能在
BaseDataFormat
中有一个名为
DataLength
的属性。要强制所有继承者设置值,请在
BaseDataFormat
的构造函数中获取长度,然后将该属性设置为数据长度

例如:

abstract class BaseDataFormat
{ 
    BaseDataFormat(int dataLength)
    {
        DataLength = dataLength;
    }

    public int DataLength { get; private set; }
    abstract void InitalizeFromBytes(byte [] );
}

class DataFormat1 : BaseDataFormat
{
    public DataFormat1() : base(3)
    {
        // ...
    }
}
当然,它不是静态级别的,但对所有继承者来说都是强制的


另一种方法是按照VirtualBlackBox的建议,用属性装饰类。唯一的问题是,AFAIK不能像抽象成员那样将属性强制到类上。

可能在
BaseDataFormat
中有一个名为
DataLength
的属性。要强制所有继承者设置值,请在
BaseDataFormat
的构造函数中获取长度,然后将该属性设置为数据长度

例如:

abstract class BaseDataFormat
{ 
    BaseDataFormat(int dataLength)
    {
        DataLength = dataLength;
    }

    public int DataLength { get; private set; }
    abstract void InitalizeFromBytes(byte [] );
}

class DataFormat1 : BaseDataFormat
{
    public DataFormat1() : base(3)
    {
        // ...
    }
}
当然,它不是静态级别的,但对所有继承者来说都是强制的


另一种方法是按照VirtualBlackBox的建议,用属性装饰类。唯一的问题是AFAIK不能像抽象成员那样将属性强制到类上。

我会为每种数据格式构建工厂对象。或者将
DataFormat
设为工厂,并调用实际数据对象
Datum
或类似的东西。然后您可以实例化工厂,并将字节缓冲区传递给它,它可以读取必要的字节并构造实际的数据对象。

我将为每个数据格式构建工厂对象。或者将
DataFormat
设为工厂,并调用实际数据对象
Datum
或类似的东西。然后您可以实例化工厂,并将字节缓冲区传递给它,它可以读取必要的字节并构造实际的数据对象。

在读取数据时,您如何知道要实例化哪个子类?从串行数据创建对象的更通用的解决方案是使用factory模式


例如:

您如何知道在读取数据时要实例化哪个子类?从串行数据创建对象的更通用的解决方案是使用factory模式


例如:

我喜欢这种方法。当你不需要的时候,很好的模式