公开List<域对象>.通过IList< interface> [英] Exposing a List<domain objects> via an IList<interface>

查看:72
本文介绍了公开List<域对象>.通过IList< interface>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a private member of type List<T> where the T are rich domain objects. The domain in my application contains many methods that expect a T.

我只想公开类型为IList<IT>的公共属性,其中T : IT. IT的占地面积很小,由DTO实现.

I want to expose only a public property of type IList<IT> where T : IT. IT has a small footprint which is implemented by a DTO.

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

Since I cannot cast a List<T> to IList<IT> I am resorting to using List<T>.ConvertAll in the property declaration.

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

Is this there a better way to do this? Faster, more elegant?

编辑以提供其他详细信息

T是一个基类,针对该基类存在许多派生类,并且这些派生类中的每一个都有许多不同的风格(在运行时加载配置).表示层中的用户可以添加/更改/删除任何配置的这些派生类的任何实例.实例也可以由用户定向链接到彼此,但是有一些复杂的规则来控制允许哪些链接;有些是在编译时已知的,有些是仅在运行时已知的(基于配置).有些情况下可能是双向链接,有些情况是交叉链接,有些情况在任一方向上都只有一个,有些则仅在一个方向上,而有些根本没有.

The T are a base class, for which a number of derived classes exist, and each of these derived classes comes in many different flavors (configurations loaded in runtime). The user in the presentation layer can add/change/remove any instances of these derived classes of any configuration. The instances can also be linked directionally to each other by the user, but there are some complex rules that govern what links are allowed; some known at compile time, some known only at runtime (based on the configurations). Some instances may be double-linked, some cross-linked, some only single in either direction, some in only one direction, and some not at all.

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

For this purpose the T contains a list of the valid targets for any such links. The presentation layer graphically highlights these valid targets and does not allow linking if the targets are not in the valid list. When any instance is newly created, changed or removed the ValidTargets list of each instance needs to be re-evaluated and may change.

T类上还有许多其他成员和方法,工厂和服务类希望在这些成员和方法上进行操作.有些行为与上面的示例非常相似.这些都不应暴露在组件外部.

There is a lot of other members and methods on the T class that the factory and services classes expect to operate on. Some behave very similar to the example above. None of these should be exposed outside of the assembly.

推荐答案

假设您可以做这样的事情:

// 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类的用户这样做是什么?

What's to stop a user of this Domain class from doing this?

public class MyFakeClass : IMyInterface { } 

...

domain.Interfaces.Add(new MyFakeClass());

显然这是有问题的,因为myList实际上是List<MyRealClass>,但是 compiler 不能确保仅将MyRealClass实例添加到列表中(这需要运行时间检查).换句话说,这种行为不是类型安全的,因此编译器将不允许这种行为.

Obviously this would be problematic because myList is in reality a List<MyRealClass>, but the compiler cannot ensure that only instances of MyRealClass are added to the list (it would require a run-time check). In other words, this kind of behavior is not type-safe, so the compiler won't allow it.

您可以公开IMyInterfaceIList/ICollection,这是类型安全的,但不能确保仅将MyRealClass添加到列表中.

You can expose a IList / ICollection of IMyInterface—which is type-safe, but doesn't ensure that only your MyRealClass is added to the list.

public class Domain
{
    private List<IMyInterface> myList;

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

或者,您可以显示 IEnumerable IMyInterface(或 IReadOnlyList ,如泛型中的协方差和协变).尽管这不允许您将新项目添加到集合中.

Alternatively, you can expose an IEnumerable of IMyInterface (or IReadOnlyList, as zmbq suggests)—since the type parameter is covariant (see Covariance and Contravariance in Generics). Although this would not allow you add new items to the collection.

public class Domain
{
    private List<MyRealClass> myList;

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

另一种解决方案是实现自己的集合类,该集合类实际上实现了IList<IMyInterface>,但是如果用户尝试插入除MyRealClass之外的任何内容,则将引发异常.这不是一个特别优雅的解决方案,并且从实际意义上讲,它与简单地公开IList<MyRealClass>没什么区别.

Another solution would be to implement your own collection class that actually implements of IList<IMyInterface> but throws an exception if a user tries to insert anything other than a MyRealClass. This isn't a particularly elegant solution and in practical terms, it's not any different from simply exposing an IList<MyRealClass>.

这篇关于公开List&lt;域对象&gt;.通过IList&lt; interface&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆