c#虚拟静态成员

时间:2017-06-27 20:42:37

标签: c# syntax static

是的,我知道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);
}

我需要......一个虚拟静态属性。

2 个答案:

答案 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 */... }方法。这样你就可以将所有实体的大小方面封装到一个单独的类中。