关于c#:将具有相同属性的匿名类型转换为接口

Cast an anonymous type with same properties to an interface

本问题已经有最佳答案,请猛点这里访问。

我正试图将具有相同属性的匿名类型强制转换为接口,但出现了一个错误:

无法将类型"<>f_uuAnonymousType104'1[system.int32]"的对象强制转换为类型"ihasFiles"。

1
2
3
4
5
6
7
 public interface IHasFiles
 {
    int FileMasterId { get; }
 }

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


这是因为接口实现是显式的,而不是动态的。

不能简单地将对象强制转换为接口引用,因为它具有相同的成员,该对象的类型也必须显式实现接口。

匿名类型不能强制转换为除objectdynamic(伪装为object)或其自身类型之外的任何类型,这也有点棘手,因为您不确切知道类型(但有…对此进行黑客攻击)。

所以不,你不能这样做。

你要找的是通常被称为"鸭子打字",也就是"如果它像鸭子一样走路,如果它像鸭子一样嘎嘎叫,那么出于所有的意图和目的,它就是一只鸭子"。这不支持stock c或.net,但可以使用代码"模仿"。

如果需要一个实现特定接口的对象,则必须声明一个实现该接口的普通命名类型,但没有(好的)方法可以绕过它。

现在,本文只提到了C编译器和/或.NET允许您执行的位。这里还有另一个概念,即使C编译器允许您这样做,也会使这个概念变得模糊。

这就是意图。

接口执行以下操作:

  • 宣布一份关于实施者必须向成员提供什么的合同
  • 声明一个合同,说明用户可以期望哪些成员可用
  • 宣布一份关于这些成员含义的合同

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

不,你不能。

现在,很明显,有很多方法可以解决这个问题,但没有一个是容易的,我会说,在大多数情况下,它们都是隐藏糟糕设计的黑客。

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

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

如果你真的想沿着这条路线走,你可以使用"即兴"nuget包,然后你的代码会如下所示:

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

但我强烈反对这一点。声明类型!