公开列表<;域对象>;经由IList<;界面>;
本文关键字:gt lt 经由 IList 界面 列表 对象 | 更新日期: 2023-09-27 18:29:46
我有一个类型为List<T>
的私有成员,其中T
是富域对象。我的应用程序中的域包含许多需要T
的方法。
我只想公开类型为IList<IT>
的公共属性,其中T : IT
。CCD_ 6具有由DTO实现的小占地面积。
由于我无法将List<T>
强制转换为IList<IT>
,所以我在属性声明中使用List<T>.ConvertAll
。
有更好的方法吗?更快、更优雅?
编辑以提供更多详细信息
T
是一个基类,存在许多派生类,这些派生类中的每一个都有许多不同的风格(在运行时加载的配置)。表示层中的用户可以添加/更改/删除任何配置的这些派生类的任何实例。用户也可以将实例定向链接到彼此,但有一些复杂的规则来管理允许的链接;有些在编译时已知,有些仅在运行时已知(基于配置)。有些实例可能是双重链接的,有些是交联的,有些在任一方向上都是单一的,有些只在一个方向上,有些根本不是。
为此,T
包含任何此类链路的有效目标的列表。表示层以图形方式高亮显示这些有效目标,如果目标不在有效列表中,则不允许链接。当任何实例被新建、更改或删除时,每个实例的ValidTargets列表都需要重新评估,并且可能会发生更改。
T
类上还有许多其他成员和方法,工厂和服务类希望对它们进行操作。有些成员和方法的行为与上面的示例非常相似。这些都不应暴露在组件外部。
假设您可以执行以下操作:
// NOT REAL CODE
public interface IMyInterface { }
public class MyRealClass : IMyInterface { }
...
public class Domain
{
private List<MyRealClass> myList;
public IList<IMyInterface> Interfaces { get { return (IList<IMyInterface>)this.myList; } }
}
如何阻止Domain
类的用户执行此操作?
public class MyFakeClass : IMyInterface { }
...
domain.Interfaces.Add(new MyFakeClass());
显然,这是有问题的,因为myList
实际上是List<MyRealClass>
,但编译器不能确保只有MyRealClass
的实例被添加到列表中(这需要运行时检查)。换句话说,这种行为不是类型安全的,所以编译器不允许这样做
您可以公开IMyInterface
的IList
/ICollection
—这是类型安全的,但不能确保只将您的MyRealClass
添加到列表中。
public class Domain
{
private List<IMyInterface> myList;
public IList<IMyInterface> Interfaces { get { return this.myList; } }
}
或者,您可以公开IMyInterface
的IEnumerable
(或IReadOnlyList
,如zmbq所建议的)—因为类型参数是协变的(参见泛型中的协变和逆变)。尽管这不允许您向集合中添加新项目。
public class Domain
{
private List<MyRealClass> myList;
public IEnumerable<IMyInterface> Interfaces { get { return this.myList; } }
}
另一个解决方案是实现您自己的集合类,该类实际上实现了IList<IMyInterface>
,但如果用户试图插入除MyRealClass
之外的任何内容,则会引发异常。这不是一个特别优雅的解决方案,而且在实践中,它与简单地公开IList<MyRealClass>
没有什么不同。
如果我理解正确,您应该能够使用Linqs-select方法将列表转换为IList。所以你在做这样的事情:
List<T> myList = ...
IList<IT> b = myList.Select(a=> a as IT).ToList();