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

Nau*_*nja 0 c# anonymous-types

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

无法将类型为“ <> 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
Run Code Online (Sandbox Code Playgroud)

ang*_*son 6

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

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

匿名类型不能强制转换为objectdynamicobject变相)或它自己的类型以外的任何其他类型,这也有些棘手,因为您不完全知道类型(但是……有一些技巧)。

所以不,你不能那样做。

您正在寻找的东西通常被称为“鸭子打字”,又名“如果它走路像鸭子一样,如果它像鸭子一样嘎嘎叫,那么无论从哪方面来看,它都是鸭子”。股票C#或.NET不支持此功能,但可以使用代码“模仿”。

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


现在,直到本文为止,本文仅指的是C#编译器和/或.NET将允许您执行的操作。这里还有另外一个概念在起作用,即使C#编译器允许您执行此操作,也会使该概念变得阴暗。

这是有目的的

接口执行以下操作:

  • 声明执行者必须向成员提供什么的合同
  • 声明有关用户对会员的期望的合同
  • 声明有关这些成员含义的合同

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

不,你不能。


显然,现在有很多方法可以解决,但没有一种方法很容易,我想说的是,在大多数情况下,它们都是隐藏不良设计的hack。

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

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

如果您真的想走这条路,可以使用下面的注释,使用“ ImpromptuInterface” nuget包,然后您的代码将如下所示:

var entity = new { FileMasterId = fileMasterId }.ActLike<IHasFiles>();
Run Code Online (Sandbox Code Playgroud)

但是我强烈建议不要这样做。声明类型!