将具有相同属性的匿名类型转换为接口

Cast an anonymous type with same properties to an interface

我正在尝试将具有相同 属性 的匿名类型转换为接口,但出现错误:

无法将“<>f__AnonymousType104`1[System.Int32]”类型的对象转换为类型 'IHasFiles'。

 public interface IHasFiles
 {
    int FileMasterId { get; }
 }

 var entity = new { FileMasterId = fileMasterId }.CastOrDefault<IHasFiles>();
 // This is the line where I get the error

那是因为接口实现是explicit,而不是dynamic

您不能仅仅因为对象具有相同的成员就将对象转换为接口引用,该对象的类型也必须显式实现接口。

除了 objectdynamic(变相的 object)或它自己的类型,匿名类型不能转换为任何类型,这也有点棘手,因为你不完全知道类型(但有...为此黑客)。

所以不,你不能那样做。

您要查找的通常称为 "duck typing",又名 "if it walks like a duck, and if it quacks like a duck, then for all intents and purposes, it is a duck"。这不受标准 C# 或 .NET 支持,但可以 "mimicked" 使用代码。

如果您需要一个实现特定接口的对象,您必须声明一个实现该接口的普通命名类型,没有 (好) 解决方法。


现在,这个 post 只是,直到这里,指的是 C# 编译器 and/or .NET 允许你做的事情。这里还有另一个概念,即使 C# 编译器允许您这样做,也会使 概念 变得可疑。

那就是意图

接口执行以下操作:

  • 声明关于实施者必须提供的成员的合同
  • 就用户对成员可用的期望签订合同
  • 声明关于这些成员的含义的契约

这最后一部分很难强加到一个类型上,即使你可以在它的头上穿一个接口。如果我写的 class 恰好与您的一个接口具有相同的成员,如果您将该接口线程化到我的 class 上,您能否强加这些成员的相同含义?

不,你不能。


现在,很明显,有 种解决方法,但 none 很容易,我想说在大多数情况下,它们都是隐藏不良设计的技巧。

在任何情况下,为了避免这种情况,您可以通过反射构建另一种类型,该类型同时包装所有成员并将其委托给您的对象类型,并在运行时实现此接口, .

这是好的设计吗?不,绝对不是。

如果您真的想走这条路,您可以按照下面的评论,使用"ImpromptuInterface" nuget包,然后您的代码将如下所示:

var entity = new { FileMasterId = fileMasterId }.ActLike<IHasFiles>();

但我 强烈反对这样做。声明类型!