namespace ClassLibrary1
public class TestClass
public void Test(dynamic obj)
Console.WriteLine(obj.Id);
编译没有问题,但是运行时会提示
“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的未经处理的异常在 System.Core.dll 中发生
其他信息: “object”未包含“Id”的定义
Id属性是肯定存在的,那问题出在哪呢?
让我们用ILDasm查看程序,会发现其实声明的匿名类型是internal级别的。
而internal只能只有在同一程序集中访问。在运行时,dynamic想找到另一个程序集中的internal类型的属性,自然会报错。
知道了原因,解决起来就很简单了,只需要在当前程序集的AssemblyInfo.cs中加上
[assembly: InternalsVisibleTo(“ClassLibrary1”)]
指定对指定程序集可见即可。
转自:在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义的输出
在很多时候,我们在数据库里面定义表字段和实际在页面中展示的内容,往往是不太匹配的,页面数据可能是多个表数据的综合体,因此除了我们在表设计的时候考虑周到外,还需要考虑数据展现的处理。如果是常规的处理,那么需要对部分外键字段进行特别的转义处理,如果需要增加多一些字段,那么这种处理可能就相对比较麻烦一些。本文介绍如何在MVC控制器里面使用dynamic和ExpandoObject,实现数据转义后一体化的输出,包括增加任意多的字段信息。
1、数据信息的展示
一般情况下,我们在界面里面展示的信息是相对比较丰富的,尽管我们设计数据表的时候,考虑的是如何精简且避免重复,但是在界面上展示的信息,往往是考虑如何让用户更加方便,因此可能尽可能的展示相关信息。
如对于这样的场景,设备信息作为主要的基础信息,其相关的业务包括设备检查、设备维护、设备报修等信息,如下所示。
基于上面的数据设计,我们如果在展示设备检查、设备维护、设备报修等信息的时候,那么我们一般还需要展示部分的设备基础信息,这样我们更容易了解整个记录数据,但是我们在数据设计的时候,是把它们分开的,因此需要在输出到界面的时候,把它们综合起来。
我以前在《基于MVC4+EasyUI的Web开发框架经验总结(9)–在Datagrid里面实现外键字段的转义操作》介绍过一些数据转义的处理,不过那种方式并不是比较理想的方式。本篇介绍的使用dynamic和ExpandoObject才是我理想的处理模式。
我们来看看我最终通过这种方式实现的界面效果,之后我们再来一步步介绍如何实现这个操作过程的。
2、数据转义的实现
在上面的界面效果里面,我们是基于MVC实现后台的处理,在界面上利用Bootstrap进行展示的(利用EaysUI组件也是类似的处理)。我们分为两部分进行介绍实现的,一部分是采用MVC的输出数据,一部分是界面的展示。
1)MVC的控制器数据处理
在MVC里面,我们一般通过基类的FindWithPager进行数据的分页处理,基于如何在MVC控制器里面实现数据的分页处理,大家感兴趣可以参考《基于Metronic的Bootstrap开发框架经验总结(2)–列表分页处理和插件JSTree的使用》随笔进行了解。
常规的做法,如果是主表信息,我们可以把它们简单的输出,如下所示。
public override ActionResult FindWithPager()
//检查用户是否有权限,否则抛出MyDenyAccessException异常
base.CheckAuthorized(AuthorizeKey.ListKey);
string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceInfo> list = baseBLL.FindWithPager(where, pagerInfo);
//Json格式的要求{total:22,rows:{}}
//构造成Json的格式传递
var result = new { total = pagerInfo.RecordCount, rows = list };
return ToJsonContentDate(result);
也就是不需要经过任何转义就直接把查询到的数据列表输出给调用者,由界面进行数据的筛选处理。
如果对于上面提到的设备检查、设备维修等和设备信息相关的,我们就需要利用dynamic和ExpandoObject,把设备信息整合一起提供给界面了,具体代码如下所示。
我们首先对查询的记录进行遍历,把每条记录进行转换,如下所示。
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
dynamic obj = new ExpandoObject();
注意上面我们定义了List的列表和dynamic obj的对象,这样我们通过动态定义的对象,把我们需要的字段属性加到动态对象里面,然后放到集合里面即可。
完整的分页控制器代码如下所示。
public override ActionResult FindWithPager()
//检查用户是否有权限,否则抛出MyDenyAccessException异常
base.CheckAuthorized(AuthorizeKey.ListKey);
string where = GetPagerCondition();
PagerInfo pagerInfo = GetPagerInfo();
List<DeviceCheckInfo> list = baseBLL.FindWithPager(where, pagerInfo);
//设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人
List<ExpandoObject> objList = new List<ExpandoObject>();
foreach (DeviceCheckInfo info in list)
dynamic obj = new ExpandoObject();
DeviceInfo deviceInfo = BLLFactory<Device>.Instance.FindByCode(info.DeviceCode);
if (deviceInfo != null)
obj.Dept = deviceInfo.Dept;
obj.Brand = deviceInfo.Brand;
obj.Name = deviceInfo.Name;
obj.Model = deviceInfo.Model;
obj.SerialNo = deviceInfo.SerialNo;
obj.ID = info.ID;
obj.DeviceCode = info.DeviceCode;
obj.OperateTime = info.OperateTime;
obj.Operator = info.Operator;
objList.Add(obj);
//Json格式的要求{total:22,rows:{}}
//构造成Json的格式传递
var result = new { total = pagerInfo.RecordCount, rows = objList };
return ToJsonContentDate(result);
2)界面的数据展示
上面定义了数据的获取方式,也就是我们需要任何数据都可以在MVC控制器里面,通过动态属性的方式添加到集合对象里面,从而简化了我们界面的处理,我们只需要把获得的信息展示在界面上即可,非常简便了。
界面视图的HTML代码如下所示
<table id="grid" class="table table-striped table-bordered table-hover" cellpadding="0" cellspacing="0" border="0" class="display" width="100%">
<thead id="grid_head">
<!--设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人 -->
<th class="table-checkbox" style="width:40px"><input class="group-checkable" type="checkbox" onclick="selectAll(this)"></th>
<th>设备编码</th>
<th>所属科室</th>
<th>品牌</th>
<th>品类</th>
<th>型号</th>
<th>设备序列号</th>
<th>检查时间</th>
<th>处理人</th>
<th style="width:90px">操作</th>
</thead>
<tbody id="grid_body"></tbody>
</table>
我们绑定到界面上,是通过Ajax的方式获取数据,然后绑定显示的,JS代码如下所示。
function SearchCondition(page, condition) {
//获取Json对象集合,并生成数据显示内容
url = "/DeviceCheck/FindWithPager?page=" + page + "&rows=" + rows;
$.getJSON(url + "&" + condition, function (data) {
$("#totalCount").text(data.total);
$("#totalPageCount").text(Math.ceil(data.total / rows));
$("#grid_body").html("");
//<!--设备编码 所属科室 品牌 品类 型号 设备序列号 检查时间 处理人 -->
$.each(data.rows, function (i, item) {
var tr = "<tr>";
tr += "<td><input class='checkboxes' type=\"checkbox\" name=\"checkbox\" value=" + item.ID + "></td>";
tr += "<td>" + item.DeviceCode + "</td>";
tr += "<td>" + item.Dept + "</td>";
tr += "<td>" + item.Brand + "</td>";
tr += "<td>" + item.Name + "</td>";
tr += "<td>" + item.Model + "</td>";
tr += "<td>" + item.SerialNo + "</td>";
tr += "<td>" + item.OperateTime + "</td>";
tr += "<td>" + item.Operator + "</td>";
tr += getActionHtml(item.ID); //获取查看、编辑、删除操作代码
tr += "</tr>";
$("#grid_body").append(tr);
//设置分页属性及处理
var element = $('#grid_paging');
if(data.total > 0) {
var options = {
bootstrapMajorVersion: 3,
currentPage: page,
numberOfPages: rows,
totalPages: Math.ceil(data.total / rows),
onPageChanged: function (event, oldPage, newPage) {
SearchCondition(newPage, condition); //页面变化时触发内容更新
element.bootstrapPaginator(options);
} else {
element.html("");
这样就最终优雅的实现了我们前面介绍的界面效果了。
后台代码:
var listMix = from a in listResult
join b in listProduct on a.ProductNum equals b.SnNum
select new
SnNum = a.SnNum,
ProductName = a.ProductName,
ProductNum = a.ProductNum,
Size = (b.Size == null ? "" : b.Size),
CateName = b.CateName,
Num = a.Num,
CreateTime = a.CreateTime,
StorageNum = a.StorageNum,
FromLocalName = a.FromLocalName,
ToLocalName = a.ToLocalName,
listMix = listMix.Distinct().ToList();
//进行expando方法替换list内容
List<ExpandoObject> listDyn=new List<ExpandoObject>();
foreach (var item in listMix)
dynamic obj = new ExpandoObject();
obj.SnNum = item.SnNum;
obj.ProductName = item.ProductName;
obj.ProductNum = item.ProductNum;
obj.Size = item.Size;
obj.CateName = item.CateName;
obj.Num = item.Num;
obj.CreateTime = item.CreateTime;
obj.StorageNum = item.StorageNum;
obj.FromLocalName = item.FromLocalName;
obj.ToLocalName = item.ToLocalName;
listDyn.Add(obj);
ViewBag.Detail = listDyn;
前台代码:
<tbody>
@foreach (var entity in ViewBag.Detail)
<td>@entity.ProductName</td>
<td>@entity.ProductNum</td>
<td>@entity.Size</td>
<td>@entity.CateName</td>
<td>@entity.FromLocalName</td>
<td>@entity.ToLocalName</td>
<td>@entity.Num</td>
</tbody>
异常类型:ConfigurationErrorsException
异常消息:未能加载文件或程序集“Microsoft.CSharp, Version=4.0.0.0, Culture=neutr
原文地址:http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=csharpfuture&DownloadId=3550(Word格式,需接受许可协议并下载。)译文地址:http://www.cnblogs.com/AndersLiu/archive/2008/11/03/1325148
简介Introduction07/01/2017本文内容C#(读作“See Sharp”)是一种简单易用的新式编程语言,不仅面向对象,还类型安全。C# (pronounced "See Sharp") is a simple, modern, object-oriented, and type-safe programming language. C # 在 C 语言系列中具有其根,并将对 C、c...
出现这个问题的原因是控制器中传给view的数据类型与View中设置的model类型不一致导致,比如控制器返回的IList类型的,而你在View里面model设置的是IEnumerable<>类型,那就会出现这种问题了,因为一个是数组类型,一个是泛型类型集合,解决办法就是保证控制器与View数据类型一致就行了
1.原因是我们在使用动态类型时,使用关键字dynamic。
2.如果调用处不是同一个类库时,会引发“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”
匿名类型是internal级别的。
其它类库是无法访问的。
解决办法:
[assembly: InternalsVisibleTo("NameSpace1.S...
抛出“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”异常,原因是匿名类型不能跨程序集(assembly)访问,解决办法有两种:
一、使用 Expando 。
二、在源程序集的AssemblyInfo.cs中加入:[assembly:
InternalsVisibleTo("NameSpace1.SubNameSpace1
关于Microsoft.CSharp.RuntimeBinder.RuntimeBinderException的异常一般来自于两种,
Predefined type 'Microsoft.CSharp.RuntimeBinder.Binder' is not defined or imported
解决它的办法是,直接在项目引用中添加 Micorsoft.Csharp 就可以了。
第二...
asp.net操作Excel合并单元格时,抛出了异常:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: “object”未包含“get_Range”的定义
在 CallSite.Target(Closure , CallSite , ComObject , Object , Object )
在 System.Dynamic.U
I am trying to compile this code in Microsoft Visual C# 2010 我正在尝试在Microsoft Visual C#2010中编译此代码
参考地址:http://www.ggat.cn/newsInfo.html/8
问题:无法访问对象的某个属性
原因1:对象被cast成object,所以当然找不到对应的属性。这类问题多出在asp.net mvc 动态属性上,比如:
ViewBag.UserName = new ...
本博客内容正在持续更新,最后一次更新时间:2020.08.30
1.本专栏的 Part 6 主要介绍作者在学习和实践中所遇到的一些程序运行问题的解决方案,如有差错或更优解,欢迎指正
2.您如果碰到有关 GH 二开的任何问题,欢迎在本专栏的任意一篇博文下留言交流
【本文重点】
1.查文档:(1) RhinoCommon SDK (2) Grasshopper API
2.专栏地址:专栏:Rhino (Grasshopper) 二次开发 (C#)
推荐阅读:
【C#】:本文以介绍 Rhino, Gra
你可以使用 dynamic 来定义一个变量或者字段,随后你可以像弱类型语言一样调用这个实例的各种方法,就像你一开始就知道这个类型的所有属性和方法一样。
但是,使用不当又会遇到各种问题,本文收集使用过程中可能会遇到的各种问题,帮助你解决掉它们。
本文内容快速入门编译错误:缺少编译器要求的成员对于 .NET Core 或者 .NET Standard 项目对于 .NET Framework 项目异常...