zoukankan      html  css  js  c++  java
  • Dll中的方法向外返回dynamic类型可能会失败

         如果Dll中有某个类的方法返回dynamic实例,并且dynamic对象实际实例为匿名类类型,则Dll的外部使用者可能最终无法正常使用此dynamic对象。当使用此dynamic对象时,可能会遇到x属性没有在object中定义的错误,此错误属于Microsoft.CSharp.RuntimeBinder.RuntimeBinderException实例——即使Debug时,能够看到返回的对象实例确实含有x属性。

    这很诡异,返回匿名类,并用dynamic进行标示是节省代码量的利器。但在此处,运行时却无法发现动态的对象类型。经过多次试验,再说明一下会出现此问题的场景:

    环境为.Net Framework 4.6 & Visual Stdio 2015 Community.

    在Dll中定义类方法,并返回dynamic。实际返回类型为匿名类型。

    /// <summary>
    /// 类库工程
    /// </summary>
    namespace dynamicdll
    {
        public class Student
        {
            public static dynamic GenerateOne()
            {
                return new { No = "1", Name = "Dong", Age = 29 };
            }

    在Dll外部调用此方法,打印其属性值。DLL外部是指在DLL工程外部,而不是不同的命名空间。

    namespace LimsTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                var st = GenerateOne();
                Debug.WriteLine($"{st.No},{st.Name},{st.Age}");

    运行以上测试代码,出现错误。

    测试方法:

    1. 在同一个.csproject中,相同的代码、使用方法不会出现此问题。
    2. 在dll项目内部使用,不会出现问题。
    3. 只有在dll中定义,外部使用才会出现问题。

    可能的原因:

    1. 程序加载Dll的一些特殊之处。可能是AppDomain加载DLL的一些机制问题。
    2. 如果字段、方法参数或者返回值的类型是dynamic,编译器会将该类型转换为System.Object,并在元数据中向字段、参数或返类型应用System.Runtime.CompilerService.DynamicAttribute的实例。从上图的错误中可以看到返回的对象已经被转换为Object,但却没有能成功应用Runtime binding。外部调用后,Runtime没有找不到合适的、或者不知道如何在执行动态运行转换。如果跟踪调试,虽然可以看到类型为匿名类,并且拥有属性(值),但是运行会失败。

    解决方案:

    返回非dynamic对象。

    不要使用匿名对象作为dynamic的返回值。使用确定的、在DLL中明确定义的类,返回dynamic不会出现错误。

    总结:

    不要在DLL中向其外部使用者返回实际类型为匿名类的dynamic对象实例。

  • 相关阅读:
    anguar使用指令写选项卡
    前端性能优化
    有关楼层般的侧导航
    我对面向对象的深刻理解
    jq中的表单验证插件------jquery.validate
    JavaScript 语言中的 this
    闭包,作用域链,垃圾回收,内存泄露
    angular.extend、angular.$watch、angular.bootstrap
    Angular路由(三)
    Angular基础(二)
  • 原文地址:https://www.cnblogs.com/jjseen/p/5530997.html
Copyright © 2011-2022 走看看