记一个动态类型问题

问题情景#

订单页面需要展示不同订单的游客信息,订单信息有一个公共数据实体,而游客有不同的两个不同的数据实体,于是就有了类似下面的代码

    public class Order
    {
        public string SerialId = string.Empty;
        public dynamic Tours = null;
    }
    var order = new Order();
    order.Tours = new List();
    order.Tours.Any();

赋值后在前台将Tours as 成我们想要的游客数据实体列表,然后在判断是否存在数据时 order.Tours.Any()报错:“System.Collections.Generic.List”未包含“Any”的定义

问题分析#

首先我们得到的确实是一个List类型,那么问题就出现在.Any()这个LINQ语句中,原因是“动态对象不支持扩展方法。lambda也不能用作动态方法调用的参数,因此LINQ不能用于动态对象。大多数LINQ调用都是扩展方法。”-C#高级编程
这是why,那么why why?

    public class Program
    {
        static void Main(string[] args)
        {
            List list = new List();
            //dynamic list = new List();
            list.Any();
        }
    }
Paste_Image.png

记一个动态类型问题_第1张图片
Paste_Image.png

看上面的代码和截图,代码编译成IL后执行过程就已经明确下来,执行需要信息完备了。但是dynamic类型编译成的IL却并没有明确这些执行信息,而是在执行IL时去查找操作的类型,生成表达式树来绑定需要的操作。 具体实现本人也还在研究中。

重要的事情来了,dynamic类型生成的IL是动态去查找类型绑定方法,然而扩展方法并不是定义在目标类型中,而只是外部的一个扩展。这时候我们自然就无法找到需要调用的方法,也就会抛出出现开头的报错信息。

解决方案#

  1. 如果目标类型确定的话,将dynamic类型强制转换成需要的类型赋值给一个中间变量,然后操作中间变量。
  2. 试着使用List来接收数据

扩展延伸#

  1. 从上面的示例我们可以知道dynamic类型生成的IL远比一般代码要多得多,所以对性能的影响肯定是有的,建议非特殊情况下能不用dynamic类型就不用。就比如本人上面的代码。
  2. 对于IL等一些比较底层的东西,也许日常工作中不需要了解,但是能了解一些绝对是有帮助的。

你可能感兴趣的:(记一个动态类型问题)