我有一个名为Foo的类,其函数类似于以下
List<Bar> LoadData();
Foo和Bar都在我想在其他项目中重用的库中。现在我正在开发一个新项目,我想继承Bar。我们称之为NewBar。
让Foo.LoadData返回NewBar列表的简单而灵活的方法是什么?我认为工厂是需要的,或者只是一个委托功能。任何人都可以提供一个例子吗?
谢谢,安迪
答案 0 :(得分:3)
可能更简单,取决于你需要什么,但如果Bar是用无参数构造函数构造的,那么泛型约束就足够了:
public List<TBar> LoadData<TBar>()
where TBar : Bar, new()
{
// return a list populated with `new TBar()`;
}
用法:
var newBars = Foo.LoadData<NewBar>();
答案 1 :(得分:2)
最简单的方法是让Bar和NewBar实现一个接口,让函数返回List<IBar>
。
就是这样或者返回object
并且施展嘉豪。
答案 2 :(得分:1)
让LoadData()
虚拟。然后在派生工厂中覆盖它。
如果派生的工厂方法仍会返回Bar
的列表,但您可以在方法实现中指定所有Bar
实例实际上都是NewBar
。这可以通过使用像Snowbear的例子中的通用方法来改变。
答案 3 :(得分:1)
这里有一些问题。由于您使用的是List<Bar>
,如果您返回List<Baz>
,这将无效,因为List<>
未执行协方差。
我的建议是重新设计它以返回IEnumerable<Bar>
并将其设为virtual
,以便在新项目中创建SubFoo
,然后您可以返回IEnumerable<Baz>
。
好的,根据你提供的新信息(你用它来填充XML列表),我会创建一个virtual protected CreateBar()
来创建一个新的bar对象并由LoadData调用()在循环中创建新的Bar
。在SubFoo
我覆盖并返回Baz
。在SubFoo
中,我将调用base.LoadData()
并填充Baz
列表,然后添加逻辑以填充Baz
中不属于Bar
的新属性。< / p>
只需使用XML Serilization,我就可以免费获得所有这些内容!
答案 4 :(得分:0)
是时候了解协方差和逆变。学习并不是一件小事。基本上我建议创建一个IBar interfarce,它会让你的生活更轻松。
了解概念msdn,但您也应继续寻找其他示例。
答案 5 :(得分:0)
读完答案后(谢谢!)我想出了以下内容。为什么这不是个好主意?
public interface IBarFactory
{
Bar Create();
}
然后将LoadData更改为:
List<Bar> LoadData(IBarFactory Factory)
{
List<Bar> MyList = new List<Bar>();
if (Factory == null)
{
MyList.Add(new Bar());
}
else
{
MyList.Add(Factory.Create());
}
// etc, etc
}
然后我只需要创建以下内容:
public class BazFactory : IBarFactory
{
Bar Create() { return new Baz() };
}
最后称之为:
MyList = LoadData(BazFactory);