【问题标题】:Can I get dynamic to work like this?我可以动态地像这样工作吗?
【发布时间】:2011-10-08 02:27:52
【问题描述】:

我有一个病人类:

class Patient {
  public string First_Name { get; set; }
  public string Last_Name { get; set; }
  public DateTime Date_of_Birth { get; set; }
}

我还有一个界面:

interface IPerson {
  string First_Name { get; }
  string Last_Name { get; }
}

在这个控制台应用程序中,我希望 Display_Person 方法能够工作。它编译但抛出运行时错误,因为 Patient 没有实现 IPerson。

class Program {
  static void Main(string[] args) {
    Patient p = new Patient { 
      First_Name = "Charles", Last_Name = "Lambert",
      Date_of_Birth = new DateTime(1976,5,12),
    };
    Display_Person(p);
  }

  static void Display_Person(dynamic person) {
    IPerson p = person;
    Console.WriteLine("{0}, {1}", p.Last_Name, p.First_Name);
  }
}

在没有 Patient 实现 IPerson 接口的情况下,我可以进行哪些代码更改以使 Display_Person 方法工作?我更喜欢可重复使用的解决方案。

更新:我希望它能够正常工作,以便获得智能感知。请看过去这个例子的琐碎性。它简短而准确地解释了我的问题。如果这是 1003 个贷款申请(打印时是一本书的大小),我不想将 20 多个接口应用到我的班级,以便我可以将相关数据分组以进行计算。我也不希望每次都输入所有这些属性。过去,智能感知的缺乏使我不再使用动态语言。 (我不懒,我很高效!)

【问题讨论】:

  • 如果你真的想让智能感知工作,像在你的例子中那样使用它,去掉 IPerson 行并将'person'参数更改为'p'。不理想,但智能感知只知道您的代码允许的程度。

标签: c# dynamic duck-typing


【解决方案1】:

您可以使用Impromptu Interface 来执行此操作。

【讨论】:

  • 和你的建议一样酷。它不适用于非公共接口。此外,如果动态类型实际上是已定义的类型,例如我的 Patient 类。它会引发Patient 未实现ActLike() 方法的运行时错误。
  • 这很奇怪,我已经广泛使用它来将动态对象转换为接口。您是否尝试过替代语法:Impromptu.ActLike<IMyInterface>(expando);
  • 如果它是公开的,它可以正常工作。 dynamicVariableName.ActLike<IInterface>() 根本不起作用。 `Impromptu.ActLike() 仅在接口公开时有效。我猜它不能反映在内部成员身上。
  • 我尝试将InternalsVisibleToAttribute 添加到程序集中,但仍然没有解决问题。我猜临时图书馆只反映公众成员。我将把我的示例代码发送到那里,看看这是否是一个错误。
  • @CharlesLambert 这不是反映内部成员的问题,它工作得很好,它正在制作一种从内部接口继承的新类型,这是困难的。 [assembly: InternalsVisibleTo("ImpromptuInterfaceDynamicAssembly")] 应该可以解决这个问题。
【解决方案2】:

如果你真的想使用动态,那为什么要转换呢?

static void Display_Person(dynamic person) {
    Console.WriteLine("{0}, {1}", person.Last_Name, person.First_Name);
}

但我仍然希望 Patient 实施 IPerson。从设计的角度来看,这会更有意义,并且类型安全意味着任何错误都会在编译时而不是运行时被捕获。

【讨论】:

    【解决方案3】:

    IPerson 是不必要的。只需像这样执行Display_Person

    static void Display_Person(dynamic person) {
        Console.WriteLine("{0}, {1}", person.Last_Name, person.First_Name);
    }
    

    只要person 实现了这些属性,就可以正常工作。

    【讨论】:

      【解决方案4】:

      不!我认为(不实施 IPatient)这是不可能的。你必须实现IPatient接口

      class Patient : IPatient {}
      

      或者删除强制转换。

      static void Display_Person(dynamic person) 
      {
          Console.WriteLine("{0}, {1}", person.Last_Name, person.First_Name);
      }
      

      【讨论】:

        猜你喜欢
        • 2017-06-04
        • 1970-01-01
        • 1970-01-01
        • 2021-09-09
        • 1970-01-01
        • 1970-01-01
        • 2011-03-11
        • 2013-02-08
        • 2015-06-04
        相关资源
        最近更新 更多