Question :
I have a method that I use to deserialize data:
public static class CustomJson<T> where T: class, new()
{
public static T Deserialize(string data)
{
try
{
return string.IsNullOrEmpty(data)
? default(T)
: Newtonsoft.Json.JsonConvert.DeserializeObject<T>(data);
}
catch (Exception ex)
{
throw new Exceptions.SerializationException(SerializationType.Json, ex);
}
}
}
The type to be used in deserialization I know only in runtime:
public void TesteCustomJson(string package, string methodName)
{
try
{
var serviceFactory = new ServiceFactory();
var service = serviceFactory.GetService<ITesteService>();
var method = service.GetType().GetMethod(methodName);
if (method != null)
{
var parameter = method.GetParameters().FirstOrDefault();
if (parameter != null)
{
var parameterType = parameter.ParameterType;
var result = Framework.Utils.Serialization.CustomJson<parameterType>.Deserialize(package);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
Doing this way does not compile, the following error is generated:
The type or namespace name ‘parameterType’ could not be found (are you missing a directive or an assembly reference?)
Is there any way to pass the type to be deserialized by knowing it only at runtime?
Answer :
You can use the following code to pass a generic type during runtime :
public static class CustomJson<T> where T : class, new()
{
public static T Deserialize(string data)
{
try
{
if (string.IsNullOrEmpty(data))
return new T();
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(data);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}
public class TestClass
{
public int Id { get; set; }
public TestClass()
{
}
}
public void TestGeneric()
{
Type custom = typeof(CustomJson<>);
Type newInstance = custom .MakeGenericType(typeof(TestClass));
MethodInfo mi = newInstance.GetMethod("Deserialize");
var res = mi.Invoke(null, new object[] { "{Id: 3}" });
}
Note the method .MakeGenericType
. Briefly, the method creates a new CustomJson<T>
with the types provided in the method. Although only T
was replaced here, it could be applied to more generic types.
Example on DotNetFiddle .