0

I have a byte array and a value defining the type of the data stored in it (string, int, ...). What is the best way to get this data? I have two options in my mind:

  1. Call a method which gives the type of the data and based on that call a method which gives me the correct data.
  2. Call a method which returns both - the data (as object) and also the type of the data (DateTime, float[], ...).

I am not sure if there is something better, nor which one of these methods is better. If
Type GiveMeDataType(); and e.g. string GiveMeString();
or
MyClass GiveMeData(); with MyClass { public Type DataType; public object Data; }

I would like to take the best approach for the best readability and maintainability (add support for additional data types and so on), so I don't think that too many switch statements in different parts of code is the best thing to do.

  • Can you give me a hint what is wrong with this question? – Artholl Jul 25 '18 at 11:03
  • Your question is confusing and I'm not sure exactly what you need. Are you aware of BitConverter? If you are, can you explain why BitConverter won't cut it? – whatsisname Jul 25 '18 at 17:32
  • @whatsisname I don't ask how to do the conversion. My question is about the problem that I get some byte array and the type to which I should convert the data. The question is about the problem that I don't know, what type of data I should expect in the rest of the code so I am looking for the best solution how to handle this without over complicating my code. – Artholl Jul 26 '18 at 6:51
1

I think a general pattern for this is as follows

public interface IData
{
    Type Type {get;set;}
    byte[] Data {get;set;}
}

and then many:

public interface IDataConverter<T>
{
    T Convert(byte[] data);
    bool CanConvert(Type type);
}

So you can make a IDataConverter for whatever types you want, and the Converter has a list of these which it loops through, calling CanConvert. If that returns true, it calls the Convert Function and returns the result

class Converter
{
    private List<object> converters;
    public void AddConverter<T>(IDataConverter<T> converter)
    {
        this.converters.Add(converter);
    }
    public T Convert<T>(IData data) where T:class
    {
        var ret = converters
                .Select(i => ((dynamic)i))
                .Where(i => i.CanConvert(data.Type))
                .FirstOrDefault()?
                .Convert(data.Data)
                ;

        return ret as T;
    }
}

Edit: as you can see shoehorning in the generic type in there is tricky. You are probably better using the same pattern but just returning object

| improve this answer | |
  • I don't see how this eliminates the need for a switch statement. There are other ways to resolve T at runtime, but they are ... difficult, and you'll probably take a reflection performance hit. – Robert Harvey Jul 25 '18 at 15:21
  • let me add more code. essentially this is the newtonsoft.com/json/help/html/CustomJsonConverter.htm – Ewan Jul 25 '18 at 15:24
  • maybe the generic doesn't work... hmmm you could replace with casting and move it up to the converter method maybe – Ewan Jul 25 '18 at 15:33
  • I suppose you could maintain a map of Type->Converter – Robert Harvey Jul 25 '18 at 16:44
  • yeah, I think CanConvert might be better for stuff like list/array/collection you could have a single converter. not 100% sure – Ewan Jul 25 '18 at 17:18
1

If you need to do different behavior at run-time depending on the type of data, you won't be able to avoid some kind of switching, although that doesn't have to literally be a switch statement.

For the data itself, the second has the advantage that you can just pass the DynamicData (or whatever you call the Type/object pair) further along to be handled later, but I'd also have a direct method for when the type is known:

DynamicData GiveMeData();
T GiveMeData<T>(); 

While a general function to get data can't do more than this, you can change the consumers of the data to handle the different types dynamically. For example:

interface IDataConsumer
{
   IResult Consume(DynamicData data);
}

...

Dictionary<Type,IDataConsumer> consumers = ...;
var data = dataSource.GiveMeData();
var result = consumers[data.DataType].Consume(data);

Under the hood that's basically still a switch statement, but one that's a lot easier to add to in future.

And of course if any of the data types share functionality, you can have them implement a common interface and handle them all together.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.