-2

Sorry for the bad title, but I wasn't sure on how to name it. I need to find a way to handle the following:

I have a class

public class Event
{
     public ushort Id;
}

This class consumer of my framework have to inherit their custom event of. So let's say if they want to create the following:

public class OnConnect : Event
{
     ...
}

The ID is used to identify in a server/client enviroment, when the serialized byte[] data is transfered, to which event you have to deserialize the byte data. So basically in the byte[] data, the first 2 bytes contain the ushort id. Then I can read this, get the associacted type and call the correct deserializer.

But as the time showed, one potential issue or wrong usage, is, that the consumer forgets to assign a unique ushort id in their custom events or use the same id for multiple events as they don't check for that. Teaching them to use an enum as an example, tended to cause some additional problems. Anyways even if it seem easy to manage, our reports claim that this is a common issue.

So I want now to automate this to remove this possible issue. But I have really hard times, finding a possible way to solve this, as I have the following structure:

  • A server/client enviroment, where the process I choose, has to deliver the same result on both ends
  • The events itself cannot be used to initialize this number as it isn't always the same order when event x is first used.

First I thought about dependency injection with an interface like IRequireId or so and on my retrieve medthod like x.componentes.Where(c=>c is IRequireId) I assign a unique id to the event and store it somewhere else and when the event is initialized I can get the id from there. The problem with this is, that I cannot ensure, that the x.components.Where is retrieving the components in the same order as on the other peers on the network. Thus different id's could be assigned.

So I think DI is off the road. Has someone else any idea, or an idea on how to make sure, that my retrievement method does save any order, so that it is the same on each peer on the network?

As of writing this I had the idea of maybe using a HashSet and write my own GetHashcode that does reproduce the same hashcode on each peer. And then iterating over the hashset and doe the DI on the IRequireId interface. But how could I write a hashcode generation that is the same on each peer on the network? That would need and id again. Damn it.

Please help x) I'm a bit lost currently. tia Synergi

EDIT

I forgot to note, as someone already asked this, why not simply add the type as a string into the byte array?

As this is a network enviroment, we do care about the size of the byte array. And if we just want to send let's say 4 bytes of data in an event and the byte[] itself is 20 bytes long because of 16 bytes of a string containing the type, than this is inacceptable.

EDIT

Thx to the hint with the class name I'm now able to solve it.

  • I use the class name to generate a hashcode
  • I can then use this to ensure order in my get method
  • And finally I can do DI with creating an ushort id

awesome thx for the help

Yosh Synergi
  • 314
  • 3
  • 12
  • 1
    Please review [ask] and provide a [mcve] of what it is you're trying to accomplish. As it stands your question isn't particularly clear about what exactly you're asking. – zzzzBov Jul 05 '17 at 17:20
  • Have you really read what I'm looking for, or are you complaining about the title? As the explenation is really clear what my current design issue is. – Yosh Synergi Jul 05 '17 at 17:23
  • 1
    I agree, your question isn't clear. Of course he read your question, do you really expect someone to ask for clarification without having read the question first? It may be clear to *you*, the author, but it isn't clear to us. –  Jul 05 '17 at 17:32
  • Yes I wasn't sure, as the comment of zzzzBov arrived, 10 secounds after I posted this. So can you please tell me what is unclear to you, so I can edit my question as for me this is 100% clear what I'm looking for – Yosh Synergi Jul 05 '17 at 17:34
  • 1
    He made his comment four minutes after your question was posted, not 10 seconds. Hover your mouse on the "19 minutes ago" bit to see the full timestamp. –  Jul 05 '17 at 17:36
  • 1
    @YoshSynergi your question rambles on without clear details about what you're attempting to achieve and little to no code to demonstrate what you've tried. Please invest some of your time to revise the question to remove the unnecessary noise. – zzzzBov Jul 05 '17 at 17:36
  • I swear I pressed the "Ask Question" button and instantly the comment arrived. But anyways, Please tell me what is unclear to you – Yosh Synergi Jul 05 '17 at 17:37
  • Someone already assisted me in finding a solution. So I don't think it was that unclear what I needed. But I will try to improve my skills on explaining my needs more the next time. – Yosh Synergi Jul 05 '17 at 17:45

2 Answers2

0

If I understand, you're serializing an object as a byte array, and you need some sort of identifier to tell you to what the original type was so that you can deserialize it to the correct type.

Instead of a number, why not just use the Type of the object you serialized? Or if this itself needs to be serialized, the name of the type? That way there's no need to match a number to a type. You already have the type.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • Yeah sorry, that is my fault I will edit to the reason for this, Basically as this is a network, we do care heavily about the size of the byte[]. And thus adding a long string of many bytes containing the type is an huge overhead. – Yosh Synergi Jul 05 '17 at 17:31
  • how about the hashcode of the type then (if you really are a high speed trading system where the addition of a string will make a difference) – pm100 Jul 05 '17 at 17:34
  • Because of this - https://stackoverflow.com/questions/8178115/why-does-system-type-gethashcode-return-the-same-value-for-all-instances-and-typ – Yosh Synergi Jul 05 '17 at 17:35
0

I solved similar situations in different ways. I will summarise the details. Choose the best option that suites you.

  • You can assign predefined Id values to your serialisers and override as necessary -

    public interface IEvent
    {
        ushort Id { get; }
    }
    
    public class Event: IEvent
    {
        public virtual ushort Id { get { return 500; } } // a generic code for generic Event
    }
    
    public class OnConnect: Event
    {
        public override ushort Id { get { return 505; } } // a more customised error code for generic Event
    }
    

    the benefit of this scenario is that you get predefined codes and no one need to assign them as they are readonly properties.

  • Second approach is using the class name as the code. Since all classes are going to have unique name, so you will always get a unique key for each event as long as you maintain the name properly. A little less rigid than the previous approach but still maintainable -

    public interface IEvent
    {
        ushort Id { get; }
    }
    
    public class Event: IEvent
    {
        public virtual ushort Id {
            get {
                var name = this.GetType().Name.Replace("Event", "");
                return name == "" ? "Generic" : name;
                //will return "Generic" for base
            }
        }
    }
    
    public class OnConnectEvent: Event
    {
        //no need to override the base class will handle everything, just make sure
        //the name is correct
        //will return "OnConnect"
    }
    
    public class OnDisconnectEvent: Event
    {
        //no need to override the base class will handle everything, just make sure
        //the names are correct
        //will return "OnDisconnect"
    }
    

    you can customise even farther by making the event class abstract, in case you don't need a generic default event.

brainless coder
  • 6,310
  • 1
  • 20
  • 36
  • Oh the class name, holy moly I never thought of this. Thanks. I will use the class name to ensure the order for my hashset on each peer, and then can use DI to generate the idea. Anyways your idea could also work with generating a string of the class name, but the bnig hint was the class name. Thx dude. – Yosh Synergi Jul 05 '17 at 17:43