2

Let's say information about a document is stored in a barcode, and the structure of the information varies according to the type of document. But the type of the document is not known beforehand; the barcode tells us what kind of document we are dealing with:

The barcode value won't store delimited strings like this:

author|date|subject
author|date|subject|approvedby1;approvedby2

but will contain json notation:

 FOO|{"author": "Smokey", "date": "01/01/2015", "subject": "widgets"}

 GOO|{"author": "Smokey", "date": "01/01/2015", "subject": "widgets", "approvals": ["Mike","Jane"]}

When we fetch the barcode text data, we see from the value to the left of the | delimiter that we need to instantiate either a FOO or a GOO. We grab the string to the right of the | and feed it to JsonConvert.

How to tell JsonConvert.DeserializeObject<some type> to return a GOO object from its json representation?

  var myGoo = JsonConvert.DeserializeObject<?>(jsonStringGOO)

What goes between the angle brackets < >?

EDIT: Ideally, without resorting to a switch statement.

Let's assume that the current namespace contains class definitions for all of the possible types.

Tim
  • 8,669
  • 31
  • 105
  • 183

4 Answers4

2

How about trying to get the type of the assembly using reflection

var data = input.Split('|');

var assembly = Assembly.LoadFrom("MyDll.dll");

var myType = assembly.GetType("My.Namespace." + data[0]); // GOO / BAR / etc

JsonConvert.DeserializeObject(data[1], myType)

Assembly.GetType(string name)

JsonConvert.DeserializeObject(string value, Type type)

N.B. for debugging, you can get the full name of the type using code like this

var t = typeof(Goo);
Debug.WriteLine(t.FullName);
ste-fu
  • 6,879
  • 3
  • 27
  • 46
  • I've used Reflection very little, and am getting an error on the Assembly.GetType line saying that `an object reference is required for the non-static field, method, or property Assembly.GetType(string)`. What reflection object must be instantiated? – Tim Aug 12 '16 at 12:45
  • Thanks. Is the dot inside or outside the quotation marks after "MyAssembly"? I assume `+ "." + ` is that right? – Tim Aug 12 '16 at 12:53
  • Sorry - another typo.It should be inside – ste-fu Aug 12 '16 at 12:55
  • I am trying `Assembly assm=Assembly.GetExecutingAssembly(); var myType=assm.GetType(assm.GetName() + ".Test.GOO");` but `myType` is null. Class `GOO` is found in namespace `Test` in the currently executing assembly. – Tim Aug 12 '16 at 13:03
  • When I remove the `assm.GetName()` and supply only the FullName of the type, then myType is assigned. Making progress. Thanks! – Tim Aug 12 '16 at 13:09
  • That sounds like a JSON.Net version error, not specifically related to this question – ste-fu Aug 12 '16 at 13:15
  • Yes, I just discovered and fixed that. Thanks very much for the help. – Tim Aug 12 '16 at 13:16
0

Assuming you have a class named GOO, the type of the call goes between the brackets. But you have to switch depending on the type:

class GOO {
  string author { get; set; }
  string date { get; set; }
  // ...
}

class FOO { 
  // ...
}

object parse(string barcode) {
  int pos = barcode.IndexOf('|');
  string type = barcode.substring(0,pos);
  string obj = barcode.substring(pos+1);
  switch(type) {
   case "GOO": return JsonConvert.DeserializeObject<GOO>(obj);
   case "FOO": return JsonConvert.DeserializeObject<FOO>(obj); 
   default: return null; // unknown type
  }
}
MarkusParker
  • 1,264
  • 2
  • 17
  • 35
  • Is there a way to do it without a switch statement? I will edit my question. – Tim Aug 12 '16 at 12:22
  • You could also use reflection to query the type by name and build the generic method using that type info. This would work without needing switch statements etc and would be extensible without recompiling – Charleh Aug 12 '16 at 12:30
-1

Do you really need to have different objects?

Because you can use a single object with all posible properties, and the non-received properties will be filled as if the come blank (or false).

I tried to add a List<string> property on a app I have who receive json and the effect is that the property has null value.

Mulflar
  • 424
  • 9
  • 22
-2

I believe this could help you : just grab the type name, get the type instance through reflection and put it into the generic type.

Community
  • 1
  • 1
Dijdkay
  • 56
  • 1
  • 5