在运行时创建的类型,作为泛型类型的类型参数

时间:2014-02-28 09:39:29

标签: c# generics

我有这个senario,我需要为json反序列化提供一个类型,如何让它动态化?

此处代码使用示例类名(rd.ds.SDK.re.sa),但在实际代码中,将使用数据库中的数据构造类型。

Type dynamicalyCreatedAtRuntime = Type.GetType("rd.ds.SDK.re.sa");

var response = webRequest.ReadJsonResponseAs<Result<AnalysisResult<dynamicalyCreatedAtRuntime>>();


public static T ReadJsonResponseAs<T>(this HttpWebRequest webRequest)
{
    using (System.IO.Stream responseStream = webRequest.GetResponse().GetResponseStream())
    {
        using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream))
        {
            T result = JsonConvert.DeserializeObject<T>(sr.ReadToEnd());

            responseStream.Close();
            return result;
        }                    
    }
}

4 个答案:

答案 0 :(得分:2)

使用JsonConvert.DeserializeObject的{​​{3}}代替:

public static object ReadJsonResponseAs(this HttpWebRequest webRequest, Type type)
{
    using (System.IO.Stream responseStream = webRequest.GetResponse().GetResponseStream())
    {
        using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream))
        {
            object result = JsonConvert.DeserializeObject(sr.ReadToEnd(), type);

            responseStream.Close();
            return result;
        }                    
    }
}

显然,您需要将结果视为object。由于在编译期间您不会知道对象的类型,因此使用泛型或使用反射来调用泛型重载是没有意义的。


您还应该创建这些类型的非通用版本:Result<T>AnalysisResult<T>

必须在运行时动态创建Result<AnalysisResult<dynamicalyCreatedAtRuntime>>等类型才能完成反射,但这样做会有0个好处。这让人反感重新设计。

答案 1 :(得分:1)

MethodInfo.MakeGenericMethod就是为了这个目的。

答案 2 :(得分:0)

如果可以,我会使用Netwonsoft.JSON(Json.Net)。

var json = ...get request body...
var type = Type.GetType("a.b.c");
var obj  = JsonConvert.DeserializeObject(json, type);

与Json.NET合作也有很多帮助。如果您无法控制类,则可能无法使用,并且需要自定义转换。

如果您绝对必须调用Generic方法,则需要使用反射来手动构建调用。这很棘手,可能不值得。

var m = webRequest.GetType().GetMethod("ReadJsonResponseAs");
var func = m.MakeGenericMethod(type);
func.Invoke(webRequest, null); /* invoke func on webRequest object, no params */

你的泛型类型是否深层嵌套?如果是这样,你可能需要单独制作每个级别。

答案 3 :(得分:0)

使用反射来获取方法,然后通过使用MakeGenericMethod提供类型参数来“构造”它:

Type dynamicalyCreatedAtRuntime = Type.GetType("rd.ds.SDK.re.sa");
MethodInfo method = webRequest.GetType().GetMethod("ReadJsonResponseAs");
MethodInfo generic = method.MakeGenericMethod(dynamicalyCreatedAtRuntime );
generic.Invoke(this, null);