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模式
例如:我喜欢这种方法。当你不需要的时候,很好的模式