通过IList <interface> </interface> </domain>公开List <domain objects =“”>

时间:2013-09-01 17:10:25

标签: c# list domain-driven-design ilist convertall

我有一个List<T>类型的私有成员,其中T是丰富的域对象。我的应用程序中的域包含许多期望T的方法。

我想只公开类型为IList<IT>的公共属性T : ITIT占地面积小,由DTO实施。

由于我无法将List<T>强制转换为IList<IT>,因此我会在属性声明中使用List<T>.ConvertAll

这有更好的方法吗?更快,更优雅?

修改以提供更多详细信息

T是一个基类,其中存在许多派生类,并且这些派生类中的每一个都有许多不同的版本(在运行时加载的配置)。表示层中的用户可以添加/更改/删除任何配置的这些派生类的任何实例。实例也可以由用户定向链接,但是有一些复杂的规则来管理允许的链接;一些在编译时已知,一些只在运行时知道(基于配置)。有些情况可能是双重关联的,有些是交叉链接的,有些只在一个方向上单一,有些只在一个方向,有些则根本没有。

为此,T包含任何此类链接的有效目标列表。表示层以图形方式突出显示这些有效目标,如果目标不在有效列表中,则不允许链接。当新创建,更改或删除任何实例时,需要重新评估每个实例的ValidTargets列表,并且可能会更改。

工厂和服务类期望在T类上有许多其他成员和方法。有些表现与上面的例子非常相似。这些都不应暴露在组件之外。

2 个答案:

答案 0 :(得分:0)

假设您可以执行以下操作:

// 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的实例添加到列表中(这需要运行时检查)。换句话说,这种行为不是类型安全的,因此编译器不允许它。

您可以公开IList / ICollection IMyInterface - 这是类型安全的,但不能确保只将MyRealClass添加到列表中。

public class Domain
{
    private List<IMyInterface> myList;

    public IList<IMyInterface> Interfaces { get { return this.myList; } }
}

或者,您可以公开IEnumerable IMyInterface(或IReadOnlyListzmbq建议) - 因为类型参数是协变的(请参阅Covariance and Contravariance in Generics )。虽然这不允许您向集合中添加新项目。

public class Domain
{
    private List<MyRealClass> myList;

    public IEnumerable<IMyInterface> Interfaces { get { return this.myList; } }
}

另一个解决方案是实现自己的实际实现IList<IMyInterface>的集合类,但如果用户尝试插入MyRealClass以外的任何内容,则抛出异常。这不是一个特别优雅的解决方案,实际上,它与简单地暴露IList<MyRealClass>没有任何区别。

答案 1 :(得分:-1)

如果我理解正确,您应该能够使用Linqs select方法将列表转换为IList。所以你正在做类似的事情:

List<T> myList = ...
IList<IT> b = myList.Select(a=> a as IT).ToList();