2010-01-21 118 views
5

我在为泛型方法指定Type时尝试使用Type参数时出现错误。C#类型参数为通用声明

Error: 'JsonFilter.JsonDataType' is a 'property' but is used like a '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的解释是,当类型被指定为泛型方法的一部分时(< 类型名称>),然后将其编译为字节。而作为属性时,它可以是任何类型,只能在运行时确定。

UPDATE

对于这个特定的问题,下面的代码更简洁。

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

我可能会完全关闭基地在这里,但它看起来像你想的通用反序列化方法与在运行时间定义的类型的工作......我不认为泛型以这种方式工作 - 它们很好,而且在设计时是“通用的”,但是它们被编译为类型特定的代码...... yuck。我缺乏理解表明。底线:我不认为你想要做什么是可能的。您不能将泛型与运行时指定类型一起使用。 – Tao 2010-01-21 15:57:30

+0

@陶:它可以使用反射来完成。在适当的环境下,这实际上是一种非常强大的技术。 – jason 2010-01-21 16:05:54

回答

14

错误

Error: ' JsonFilter.JsonDataType ' is a 'property' but is used like a 'type'

告诉你确切的问题。

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

在这里,你试图传递JsonDataType作为一个类型参数的泛型方法JavaScriptSerializer.Deserialize<T>

但这里

public Type JsonDataType { get; set; } 

你宣布JsonDataTypeType类型的属性,但不作为一种。要使用泛型方法,您需要传递一个类型参数(或者,在某些情况下,让编译器推断它)。例如

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 }); 
+0

确实如此。这是对问题的一个很好的解释。 – 2010-01-21 16:00:03

+0

您好,我收到以下行中发现异常的模糊匹配: typeof(JavaScriptSerializer).GetMethod(“Deserialize”).GetGenericMethodDefinition(); 你有一个想法,为什么错误被抛出? :( – 2010-05-04 16:11:01

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

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

+0

为什么downvote? – 2010-01-21 16:00:35

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

+0

“泛型类型不能派生自'ActionFilterAttribute',因为它是一个属性类”...不能使属性通用。“ – 2010-01-21 15:59:22

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); 
     //... 
    } 
} 

+0

”泛型类型不能派生自'ActionFilterAttribute',因为它是一个属性类“...不能使属性通用。 – 2010-01-21 16:00:56

+0

@Greg,在这种情况下,然后我想用更新的答案,使用反射,是要走的路 – LukeH 2010-01-21 16:23:30

+0

是的,虽然,如你所知,在其他案例中,你最初的想法显然更好。 – 2010-01-21 17:57:03