首页 新闻 会员 周边 捐助

.net 4.0的dynamic问题求解

0
悬赏园豆:10 [已解决问题] 解决于 2012-04-28 10:43

写了一个基于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),但运行的时候报告错误:

求解!

无之无的主页 无之无 | 大侠五级 | 园豆:5095
提问于:2012-04-17 21:00
< >
分享
最佳答案
0

比较简单的做法是将你的匿名对象 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(); 就可以了。

收获园豆:7
水牛刀刀 | 大侠五级 |园豆:6350 | 2012-04-18 11:04

这个倒是一个办法,但还是有点麻烦。真奇怪,MS怎么搞出这么垃圾的东西。

无之无 | 园豆:5095 (大侠五级) | 2012-04-18 11:08

@笨笨蜗牛: 这是因为匿名对象总是会被编译成internal的,你在cshtml代码里写的匿名对象,会被编译到一个随机名字的(用来装所有view里对象的)dll里,而你的那个接受dynamic参数的方法是在另外一个dll里,匿名对象的类型对它不可见,只能作为object处理。MS把匿名对象统一处理成internal跟MVC无关,只是这里MVC中qiang了而已。MVC正在不断改进中,相信以后会有更好的解决方案吧。ASP.NET MVC 2中,你在action里构建一个dynamic的model,在view里也是不可见的,后来3就出了ViewBag来解决这个问题。框架总是在进步的,先忍忍吧。

水牛刀刀 | 园豆:6350 (大侠五级) | 2012-04-18 11:14

@水牛刀刀: 我倒没留意过匿名类的访问类型,曾经跟踪过,发现属性是public的。看来,这个问题还真的只有通过你说的这个方案来解决了。

无之无 | 园豆:5095 (大侠五级) | 2012-04-18 16:59
其他回答(2)
0

这样写是有问题的,建议创建一个包含Name和Value属性的实体,然后这样写:

new TestClass{Name="name",Value="value"}

参考:MVC Razor dynamic model, 'object' does not contain definition for 'PropertyName'

收获园豆:2
artwl | 园豆:16736 (专家六级) | 2012-04-17 22:30

我也知道通过一个实体能轻松的解决,关键是这样很麻烦,因为类似的结构会不断的变换。

支持(0) 反对(0) 无之无 | 园豆:5095 (大侠五级) | 2012-04-18 09:16
0

你創建的實體是object類型。因此 沒有name,value屬性。

收获园豆:1
無限遐想 | 园豆:3740 (老鸟四级) | 2012-04-18 09:17
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册