Passing a (local) variable to a generic method as Type

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

Upvotes: 0

Views: 1157

Answers (2)

kagetoki
kagetoki

Reputation: 4787

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.

Upvotes: 1

hazevich
hazevich

Reputation: 478

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

Upvotes: 2

Related Questions