0

What I want to do, in very short version Summary:

var localType = typeof(MyDTOClass);
var result = MyGenericMethod<localType>(string path);

VisualStudio is telling me that dtoType is variable but is used like a type.

Long version: I have the following dictionary, which is used to read some files from disk then using a (de)serializer convert it into objects. Contents of json files are almost identical so I am only putting one as example: Json Contents,array of objects:

[{
"id": "1",
"areaType": "2",
"backgroundImagePath": "path",}, {
"id": "2",
"areaType": "2",
"backgroundImagePath": "path",}, {
"id": "99",
"areaType": "1",
"backgroundImagePath": "path",}]

Dictionary Contents:

var filesToParse = new Dictionary<string, Type>{
    { "area.json",typeof(AreaDto) },
    { "areaObject.json",typeof(AreaObjectDto) },
    { "monsterSymbol.json",typeof(MonsterSymbolDto) },
};

Code to retrieve contents of contents of json:

IEnumerable GetDeserializedJson(string pathToJsonFile, Type dtoType) {
    IEnumerable result;
    using (TextReader file = File.OpenText(pathToJsonFile)) {
    result = JsonSerializer.DeserializeFromReader<IEnumerable<dtoType>>(file);
    }
    return result.OfType<dtoType>.Where(x => x != null);
}

My problem is with the following lines

result = JsonSerializer.DeserializeFromReader<dtoType>(file);
result.OfType<dtoType>.Where(x => x != null);

dtoType is variable but is used like a type. I know it is a variable but it is a variable of Type. Can you please explain me why i cant pass this type variable and if possible how to further move with my problem. The following is how I (want to) call my GetDeserializedJson

foreach(var keyValuePair in filesToParse){
    GetDeserializedJson<keyValuePair.Value>(keyValuePair.Key);
}

Thanks in advance

Hasan Emrah Süngü
  • 3,488
  • 1
  • 15
  • 33
  • 1
    Can't you make the `GetDeserializedJson` method generic as well? – Lasse V. Karlsen Jun 27 '16 at 09:16
  • 1
    Possible duplicate of [How do I use reflection to call a generic method?](http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to-call-a-generic-method) – Martin Brown Jun 27 '16 at 09:23
  • 1
    @EmrahSüngü, I think your problem is exactly the one in that link: you have a generic function that you want to call, but you have the type as a variable. If you cannot change the `GetDeserializedJson` method, maybe you could try the reflection approach. – Paolo Tedesco Jun 27 '16 at 09:28

2 Answers2

2

Simply use nongeneric DeserializeFromReader(reader, Type) method, it will return you an object. Something like this:

result = JsonSerializer.DeserializeFromReader(file, typeof(dtotype));

or if dtoType is instance of a Type then simply

result = JsonSerializer.DeserializeFromReader(file, dtotype);
hazevich
  • 438
  • 5
  • 10
  • Should the first one be without the `typeof` in there? dtoType in the OP's code is a `Type` so you probably don't want the typeof as standard (and you cover the situation where it isn't a type afterwards). – Chris Jun 27 '16 at 09:37
  • @Chris yep, you're right, but it's the second one. Thanks :) – hazevich Jun 27 '16 at 09:55
  • @hazevich: Ah yes. Language gets very confusing when talking about whether a variables type is of type `Type` and such like. – Chris Jun 27 '16 at 10:03
  • @hazevich thank you very much for your comment. After I get my object how can i proceed to cast it into`code >`? – Hasan Emrah Süngü Jun 27 '16 at 10:05
  • @EmrahSüngü to cast something, in this case I would say unbox type, you need actualy know type at compile time. I would have some class for each type, which will have some method with an argument of type object and it will know how to unbox it to it's actual type with an extra validation. – hazevich Jun 27 '16 at 10:34
1

You have to decide whether you'd like to use generics or types, but you can not 'switch' to generics on the fly. Speaking of this example

var localType = typeof(MyDTOClass);
var result = MyGenericMethod<localType>(string path);

you just don't need first line, instead it should be

 var result = MyGenericMethod<MyDTOClass>(string path);

Speaking of other sample

IEnumerable GetDeserializedJson(string pathToJsonFile, Type dtoType) 
{
     IEnumerable result;
     using (TextReader file = File.OpenText(pathToJsonFile)) 
     {
          result = JsonSerializer.DeserializeFromReader<IEnumerable<dtoType>>(file);
     }
     return result.OfType<dtoType>.Where(x => x != null);
}

You can declare generic method instead:

IEnumerable<TDto> GetDeserializedJson<TDto>(string pathToJsonFile) where TDto : DtoBaseClass
{
     IEnumerable<TDto> result;
     using (TextReader file = File.OpenText(pathToJsonFile)) 
     {
          result = JsonSerializer.DeserializeFromReader<IEnumerable<TDto>>(file);
     }
     return result.OfType<TDto>.Where(x => x != null);
}

In this way you don't even have to cast to your type and you have constraint where TDto : DtoBaseClass so compiler will not allow you use classes, not derived from you base dto class.

kagetoki
  • 4,339
  • 3
  • 14
  • 17