简体   繁体   中英

c# virtual static members

Yeah, I know there aren't any virtual static members in c#, but I have a problem where they would be really helpful and I can't see a good way to proceed.

I've got a standard kind of system where I send packets of data over a communication channel and get back responses. The communication system needs to know how many bytes of response to wait for, and the length of the response is fixed for each command type, so I have this code defined:

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) { }
}

Notice that in each case, ReceiveLength is a fixed value - sometimes it's a simple constant ( 3 ), sometimes it's a static member of some other class ( DataObject.FixedLength ) and sometimes it's the return value from a member function of a static member ( Helper.DataLength() ) but it's always a fixed value.

So that's all good, I can write code like this:

void Communicate(IPacket packet)
{
   Send(packet.DataToSend());
   WaitToReceive(packet.ReceiveLength);
}

and it works perfectly.

But now I would like to output a summary of the packets. I want a table that shows the command name (the class name) and the corresponding ReceiveLength. I want to be able to write this (pseudo)code:

foreach (Class cls in myApp)
{
   if (cls.Implements(IPacket))
   {
      Debug.WriteLine("Class " + cls.Name + " receive length " + cls.ReceiveLength);
   }
}

But of course ReceiveLength requires an object.

I don't think I can use attributes here, c# won't let me say:

[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) { }
}

because custom attributes are created at compile time (right?), long before the static constructor gets called.

Constructing objects of each type isn't particularly pleasant (pseudocode again):

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

I need ... a virtual static property.

Just make a public static CommandX.Length property, have it return what your ReceiveLength property is now, then have ReceiveLength refer to it. To get the best of both worlds, first you need both worlds.

One solution would be to throw all compile-time safety over board and simply use reflection to access your static property like so: http://fczaja.blogspot.ch/2008/07/accessing-static-properties-using-c.html

Alternatively, you could separate out that information into a "PaketSizeManager" type which would simply have either the above-mentioned Dictionary or some switch-case statement plus some neat way to access this information from the outside, as in a public int GetSize(Type t){ .../* use dictionary or switch-case here */... } method. That way you would have encapsulated the size aspect of all your entities into a separate class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM