写了一个基于MVC的站点,由多个模块组成,在一个公共模块中定义了这样的一个助手类:
public static class HtmlTagUtility { public static string BuildTagHtml(string tagName, string value, params dynamic[] attributes) { StringBuilder builder = new StringBuilder(); builder.AppendFormat("<{0}", tagName); foreach (dynamic item in attributes) { builder.AppendFormat(" {0}=\"{1}\"", item.Name, item.Value); } if (string.IsNullOrEmpty(value)) { builder.Append(" />"); } else { builder.AppendFormat(" >{0}</{1}>", value, tagName); } return builder.ToString(); } }
在站点模块的CSHTML中如此调用:
Func<System.Xml.Linq.XElement, string> imgHandler = (e) => { return HtmlTagUtility.BuildTagHtml("img", null, new { Name = "src", Value = urlHandler(e.Attributes("Image").Select(o => o.Value).SingleOrDefault()) }, new { Name = "alt", Value = e.Attributes("Title").Select(o => o.Value).SingleOrDefault() }); }; Func<System.Xml.Linq.XElement, string> anchorHandler = (e) => { return HtmlTagUtility.BuildTagHtml("a", null, new { Name = "target", Value = "_blank" }, new { Name = "href", Value = urlHandler(e.Attributes("Url").Select(o => o.Value).SingleOrDefault()) }, new { Name = "title", Value = e.Attributes("Title").Select(o => o.Value).SingleOrDefault() }); };
编译没有问题(所有的模块都引用了System.Core和Microsoft.CSharp这两个DLL),但运行的时候报告错误:
求解!
比较简单的做法是将你的匿名对象 new { Name = "xxx", Value = "yyy" } 都转成动态对象然后再作为dynamic参数传过去。你可以使用这样一个扩展方法:
public static ExpandoObject ToDynamic(this object obj) { IDictionary<string, object> dict = new RouteValueDictionary(obj); IDictionary<string, object> dynamicObj = new ExpandoObject();
foreach (var item in dict)
{ dynamicObj.Add(item);
} return (ExpandoObject)dynamicObj; }
然后将你的参数改成: new { Name = "xxx", Value = "yyy" }.ToDynamic(); 就可以了。
这个倒是一个办法,但还是有点麻烦。真奇怪,MS怎么搞出这么垃圾的东西。
@笨笨蜗牛: 这是因为匿名对象总是会被编译成internal的,你在cshtml代码里写的匿名对象,会被编译到一个随机名字的(用来装所有view里对象的)dll里,而你的那个接受dynamic参数的方法是在另外一个dll里,匿名对象的类型对它不可见,只能作为object处理。MS把匿名对象统一处理成internal跟MVC无关,只是这里MVC中qiang了而已。MVC正在不断改进中,相信以后会有更好的解决方案吧。ASP.NET MVC 2中,你在action里构建一个dynamic的model,在view里也是不可见的,后来3就出了ViewBag来解决这个问题。框架总是在进步的,先忍忍吧。
@水牛刀刀: 我倒没留意过匿名类的访问类型,曾经跟踪过,发现属性是public的。看来,这个问题还真的只有通过你说的这个方案来解决了。
这样写是有问题的,建议创建一个包含Name和Value属性的实体,然后这样写:
new TestClass{Name="name",Value="value"}
参考:MVC Razor dynamic model, 'object' does not contain definition for 'PropertyName'
我也知道通过一个实体能轻松的解决,关键是这样很麻烦,因为类似的结构会不断的变换。
你創建的實體是object類型。因此 沒有name,value屬性。