我有一个与C#/ OO / Design相关的问题。
我正在重新设计一个移植到C#的旧系统。我们正在重构系统,使其更简单,更面向对象。
在这个系统中,我们有各种与我们的业务领域相关的对象 - 文件夹,文档,用户,约会,任务等。所有这些对象都从一个被调用的基础对象继承,信不信由你,BaseObject:
public class BaseObject {
public int Id { get; set; }
public string Name { get; set; }
}
这个对象不是抽象的,因为我们实际上是为一些简单的列表实例化它。
我们也有自己的通用列表:
public class CustomList<T> : IENumerable<T> where T : BaseObject {
//... several properties and methods
}
}
我的问题是:我有很多从BaseObject继承的对象。例如,我可以创建CustomList<User>
,因为User : BaseObject
。
但是,我的许多用户控件都返回CustomList<BaseObject>
,因为这是大多数基于列表的用户控件可以返回的内容:它们知道每个对象的名称,因为它们显示的是什么,并且它们使用其ID作为键
因此,我希望能够将CustomList<BaseObject>
中的项目添加到任何CustomList<T>
。我希望能够添加对象,而不仅仅是构建一个新列表。
但是因为我不能只是从超类(BaseObject)转换为子类(例如User),所以我在考虑在CustomList<T>
中实现以下方法:
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
foreach (var item in items)
{
var newObject = constructor(item);
Add(newObject);
}
}
或者换句话说,如果一个类需要从CustomList创建一个CustomList,它需要提供CustomList和一个方法,说明如何从BaseObject构造T的每个新实例,以及如何初始化其他成员哪个BaseObject不知道。
我认为这类似于策略模式。当然这个方法本身几乎没有任何代码,但是由于这种行为无处不在,设计它的时间仍然更短。
问题是 - 这是一个好的设计吗?是否有更好的模式来处理将简化版本的对象从UI移动到实际对象的情况?
答案 0 :(得分:2)
基本上,您已经实现了类似于Linq的Select
函数的某种功能 map 函数。如今很多人都喜欢功能风格而不是普通的OOP。您的AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
是一种简单而干净的方式,可以满足您的需求。
使用Linq的另一种方式可能是
public static CustomList<T> ToCustomList<T>(this IEnumerable<T> items)
where T : BaseObject
{
var customList = new CustomList<T>();
foreach(var item in items)
customList.Add(item);
}
然后像
一样使用它IEnumerable<BaseObject> items = ...;
Func<BaseObject, T> constructor = ...;
// Usage would be
CustomList<T> customItems =
(from i in items
select constructor).ToCustomList();
// or
CustomList<T> customItems = items.Select(constructor).ToCustomList();
不创建新列表
public void AddRangeOfBaseObjects(IEnumerable<BaseObject> items, Func<BaseObject, T> constructor)
{
// AddRange from List<T>
AddRange(items.Select(constructor);
}