C#Type参数为通用声明

时间:2010-01-21 15:51:31

标签: c# generics

在为泛型方法指定Type时尝试使用Type参数时出错。

  

错误:'JsonFilter.JsonDataType'是'属性',但用作'type'

public class JsonFilter : ActionFilterAttribute
{
    public Type JsonDataType { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ...
        JavaScriptSerializer jss = new JavaScriptSerializer();
        var result = jss.Deserialize<JsonDataType>(inputContent);//Error here
        ...

新代码

...
JavaScriptSerializer jss = new JavaScriptSerializer();
MethodInfo method = jss.GetType()
               .GetMethod("Deserialize")
               .MakeGenericMethod(new Type[] { JsonDataType });
var result = method.Invoke(jss, new object[] { inputContent });
filterContext.ActionParameters[Param] = result;
...

反射可以节省一天。感谢@Jason解释当type被指定为泛型方法的一部分(&lt; Typename &gt;)时,它会被编译成字节。而作为属性,它可以是任何类型,只能在运行时确定。

更新

对于此特定问题,以下代码更简洁。

var o = new DataContractJsonSerializer(JsonDataType).ReadObject(
    filterContext.HttpContext.Request.InputStream);
filterContext.ActionParameters[Param] = o;

4 个答案:

答案 0 :(得分:14)

错误

  

错误:'JsonFilter.JsonDataType'是'属性',但用作“类型”

告诉你确切的问题。

var result = jss.Deserialize<JsonDataType>(inputContent);

在这里,您尝试将JsonDataType作为类型参数传递给通用方法JavaScriptSerializer.Deserialize<T>

但是这里

public Type JsonDataType { get; set; }

您将JsonDataType声明为Type类型的属性,但不是类型。要使用泛型方法,您需要传递一个类型参数(或者,在某些情况下,让编译器推断一个)。例如

var result = jss.Deserialize<string>(inputContent);

是正确的用法,因为string是一种类型。

现在,如果您绝对想要使用由JsonDataType表示的类型,则可以使用反射。

MethodInfo generic = typeof(JavaScriptSerializer).GetMethod("Deserialize")
                                                 .GetGenericMethodDefinition();
MethodInfo closed = generic.MakeGenericMethod(new [] { JsonDataType });
closed.Invoke(jss, new object[] { inputContent });

答案 1 :(得分:5)

由于您无法在类中添加泛型类型参数,因此您需要使用反射:

public class JsonFilter : ActionFilterAttribute
{
    public Type JsonDataType { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // ...
        JavaScriptSerializer jss = new JavaScriptSerializer();

        MethodInfo method = jss.GetType()
                               .GetMethod("Deserialize");
                               .MakeGenericMethod(new Type[] { JsonDataType });
        var result = method.Invoke(jss, new object[] { inputContent });
        //...
    }
}

原创,错误回答......

<击> 您可以使用泛型类型参数而不是JsonDataType属性吗?

public class JsonFilter<TJsonData> : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // ...
        JavaScriptSerializer jss = new JavaScriptSerializer();
        var result = jss.Deserialize<TJsonData>(inputContent);
        //...
    }
}

<击>

答案 2 :(得分:2)

沿着这些方向尝试这个。我会在一秒钟内为您的代码更新它。

typeof(IDependencyResolver).GetMethod("Resolve", new Type[] { })
                .MakeGenericMethod(type)
                .Invoke(this, null);

这是给你的草稿。

typeof(JavaScriptSerializer).GetMethod("Deserialize", new Type[] {} /* param types */)
    .MakeGenericMethod(JsonDataType).Invoke(jss, /*params*/);

基本上它使用反射来调用泛型方法。

答案 3 :(得分:2)

你不能以这种方式传递泛型类型的参数 - 尝试这样的事情:

public class JsonFilter<T> : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        JavaScriptSerializer jss = new JavaScriptSerializer();
        var result = jss.Deserialize<T>(inputContent);//Error here
    }
}

不要在属性中设置类型,而是将JsonFilter类设为通用类,以便将泛型类型参数传递给JavaScriptSerializer