是的,我知道c#中没有任何虚拟静态成员,但我有一个问题,他们真的很有帮助,我看不到一个好的方法继续。
我有一个标准的系统,我通过通信渠道发送数据包并得到回复。通信系统需要知道要等待多少字节的响应,并且每个命令类型的响应长度都是固定的,所以我定义了这个代码:
public abstract class IPacket
{
public abstract int ReceiveLength { get; }
public abstract byte[] DataToSend();
}
public class Command1 : IPacket
{
public override int ReceiveLength { get { return 3; } }
public Command1() { }
}
public class Command2 : IPacket
{
public override int ReceiveLength { get { return DataObject.FixedLength; } }
public Command2(int x) { }
}
public class Command3 : IPacket
{
static DataHelperObject Helper;
public override int ReceiveLength { get { return Helper.DataLength(); } }
static Command3()
{
Helper = new DataHelperObject();
}
public Command3(really long list of parameters containing many objects that are a pain to set up) { }
}
请注意,在每种情况下,ReceiveLength都是固定值 - 有时它是一个简单的常量(3
),有时候它是某个其他类(DataObject.FixedLength
)的静态成员有时它是静态成员(Helper.DataLength()
)的成员函数的返回值,但它总是一个固定的值。
所以这一切都很好,我可以编写这样的代码:
void Communicate(IPacket packet)
{
Send(packet.DataToSend());
WaitToReceive(packet.ReceiveLength);
}
它完美无缺。
但是现在我想输出数据包的摘要。我想要一个表格,显示命令名称(类名称)和相应的ReceiveLength。我希望能够编写这个(伪)代码:
foreach (Class cls in myApp)
{
if (cls.Implements(IPacket))
{
Debug.WriteLine("Class " + cls.Name + " receive length " + cls.ReceiveLength);
}
}
但是当然ReceiveLength需要一个对象。
我不认为我可以在这里使用属性,c#不会让我说:
[PacketParameters(ReceiveLength=Helper.DataLength())]
public class Command3 : IPacket
{
static DataHelperObject Helper;
static Command3()
{
Helper = new DataHelperObject();
}
public Command3(really long list of parameters containing many objects that are a pain to set up) { }
}
因为自定义属性是在编译时创建的(对吗?),早在静态构造函数被调用之前。
构造每种类型的对象并不特别令人愉快(再次伪代码):
foreach (Class cls in myApp)
{
IPacket onePacket;
if (cls is Command1)
onePacket = new Command1();
else if (cls is Command2)
onePacket = new Command2(3);
else if (cls is Command3)
{
Generate a bunch of objects that are a pain to create
onePacket = new Command3(those objects);
}
Debug.WriteLine("Class " + cls.Name + " receive length " + onePacket.ReceiveLength);
}
我需要......一个虚拟静态属性。
答案 0 :(得分:0)
只需创建一个public static CommandX.Length
属性,让它返回您ReceiveLength
属性的内容,然后让ReceiveLength
引用它。为了获得两全其美,首先你需要两个世界。
答案 1 :(得分:0)
一种解决方案是将所有编译时安全性抛到一边,只需使用反射来访问静态属性,如下所示:http://fczaja.blogspot.ch/2008/07/accessing-static-properties-using-c.html
或者,您可以将该信息分离到" PaketSizeManager"类型,它只是上面提到的字典或一些switch-case语句加上一些从外部访问此信息的简洁方法,如public int GetSize(Type t){ .../* use dictionary or switch-case here */... }
方法。这样你就可以将所有实体的大小方面封装到一个单独的类中。