我有2个独立的类A和B,我有一个Storage类来管理A类和B类对象的存储。
我正在尝试抽象执行A和B存储的代码,但由于List协方差而导致我陷入困境,我无法在以下代码中分配List<object> objList = new List<A>();
。
[DataContract]
public class A {
public int UID;
}
[DataContract]
public class B {
public int UID;
}
public class Storage {
public void Store(A a) {
List<A> aList = ReadA();
if (aList == null) {
aList = new List<A>();
}
aList.Add(a);
WriteNodes(aList);
}
public void StoreB(B b) {
List<B> bList = ReadB();
if (bList == null) {
bList = new List<B>();
}
bList.Add(b);
WriteNodes(bList);
}
public List<A> ReadA() {
//deserializes from aFileName and returns List<A>
}
public List<B> ReadB() {
//deserializes from bFileName adn returns List<B>
}
private static void WriteNodes<T>(List<T> nodeList) {
FileStream fs = new FileStream(aFileName, FileMode.Create);
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs);
DataContractSerializer ser =
new DataContractSerializer(typeof(List<T>));
ser.WriteObject(writer, nodeList);
writer.Close();
fs.Close();
}
}
如果查看StoreA和StoreB方法,除了使用的类型外,它们具有通用模式。 ReadA和ReadB没问题我可以把类型作为另一个参数并创建一个单独的函数Read。
那么可以为Store创建一个抽象,所以我最终不会使用StoreA和StoreB方法吗?
答案 0 :(得分:2)
怎么样:
public void Store<T>(T a) {
List<T> aList = Read<T>();
if (aList == null) {
aList = new List<T>();
}
aList.Add(a);
WriteNodes(aList);
}
public List<T> Read<T>() {
//Read a or b depend on T
}
答案 1 :(得分:1)
是的,您可以通过引入要提交的项目的公共接口并将项目类型提取到枚举中来实现。
<强>存储强>
public class Storage
{
public Storage()
{
// create it once on construction stage
// so you do not need to check for null each time in Sore()/Read()
this.AllItems = new List<IItem>();
}
public IList<IItem> AllItems { get; private set; }
public void Store<TItem>(TItem item)
where TItem: IItem
{
this.AllItems.Add(item);
}
public IEnumerable<IItem> Read(StorageItemType itemType)
{
return this.AllItems.Where(item => item.ItemType == itemType);
}
}
抽象存储项目类型(更通用的解决方案):
// Item types
enum StorageItemType
{
A,
B
}
interface IItem
{
int UID { get; }
StorageItemType ItemType { get; }
}
public abstract class StorageItemBase: IItem
{
public int UID { get; private set; }
public abstract StorageItemType ItemType
}
public sealed class B : StorageItemBase
{
public override StorageItemType ItemType
{
get
{
return StorageItemType.B; // !!!
}
}
}