2009-10-14 103 views
0

我正在存储具有不同格式和长度的数据。我有一个类层次结构来表示:C#继承设计模式问题

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

class DataFormat1 : BaseDataFormat{...} // data stored in 3 bytes 
class DataFormat2 : BaseDataFormat{...} /// data stored in 4 bytes 

当我(从一个byte []说),我需要知道的长度(字节数)来读取并适当地创建相应类型的阅读我的数据。 DataFormat1和DataFormat2具有不同的长度,因此如何在运行时获取此信息?即。

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

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

} 

如何根据DATAFORMATTYPE对正确的字节数进行编码?每个的长度感觉应该是数据格式类型的静态属性,但静态属性不能被派生类重写,所以我不知道如何执行此操作。

长度可以编码为一个实例属性,但是这看起来应该是在类级别(即静态)编码的知识。有没有解决这个问题的设计模式?

感谢

回答

2

也许有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) 
    { 
     // ... 
    } 
} 

当然,这不是在静态的水平,但它的东西是强迫所有的继承者。

另一种方法是如何使用VirtualBlackFox建议使用属性来修饰类。唯一的问题是,AFAIK你不能强制属性到一个类,就像抽象成员一样。

0

最好的,如果你真的要强制它是类的属性,而不是实例是对类使用的属性。

但是您需要从中建立缓存,因为与直接访问相比,反射速度较慢。

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

(代码有没有错误的管理,但它的工作)

至于说通过这种方法的问题darkassassin93之一是,你不能强制它的存在,所以你必须记录此属性是必要的,与编译器为您完成工作的抽象属性相反。

1

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

+0

我喜欢这种方法。当你不想陷入实例化的细节时,这种良好的模式;并且可以将它传递给字节缓冲区并让它算出来。 – gn22 2009-10-14 22:42:15

+0

无论对于特定问题(在哪里存储字节数)的内部解决方案是什么,工厂模式都非常明显。 – 2009-10-14 22:52:52