在泛型方法中处理类特定属性

时间:2013-12-20 15:30:49

标签: c# generics

我仍然围绕着仿制药,并且遇到了我想要正确解决的挑战。如果我有几个类定义如下:

public abstract class DocBase {
    public long ID { get; set; }                                    
    public string Description { get; set; }             
    public long DocumentID { get; set; }                
    public string DocumentDate { get; set; }            
    ...snipped...
}

public class AppDoc : DocBase {
    public string A { get; set; }                                    
    public string B { get; set; }             
    public string C { get; set; }                    
}

public class OtherDoc : DocBase {
    public string D { get; set; }                                    
    public string E { get; set; }             
    public string F { get; set; }                    
}

我有一个用于检索这些文件的课程

public class Repo<T> where T : DocBase, new() 

该类将包含一个方法:

public List<T> GetDocs()

在这个方法中,我希望能够访问派生类中定义的属性(因此在AppDoc中:A,B,C和在OtherDoc中:D,E,F)。但是如果我声明一个像这样的新对象:

var doc = new T();

在设计时我只有基类(DocBase)中可用的属性,而不是dervied类(AppDoc和OtherDoc)。我如何获得属性A,B,C,D,E和F?

编辑:详细说明我的“我怎么去......”。我需要从我从数据库返回的结果列表中填充GetDocs()方法中的属性A,B,C,D,E和F.

public List<T> GetDocs(){    

var results = someService.GetMyDocuments();
var documents = new List<T>();

    foreach(IRepositoryRow row in results) {
        var newDoc = new T();

        newDoc.A = row.GetProperty("AFromDatabase").ToString();
        newDoc.B = row.GetProperty("BFromDatabase").ToString();

        documents.Add(newDoc);    
    }

    return documents;
}

2 个答案:

答案 0 :(得分:2)

这通常是有缺陷的。您的设计将完全违反多态性的规律,因为您希望访问只有基类信息可用的派生类属性。

所以问题不是我怎么能...... 我的设计出了什么问题?

修改: OR Mappers(例如Entity Framework或NHibernate)可以自动为您处理此类多态方案。我建议你走这条路。

答案 1 :(得分:1)

这取决于你想要对这些属性做什么。

如果你正在操纵它们(例如填充它们或根据它们计算thords)那么就可以在你的T上安全地调用DocBase DoStuff上的抽象方法,它可以做你想做的任何事情与属性。

如果你想根据对象做什么做不同的事情,那么这并不是非常通用的,你可能想要重新思考一些事情,最好是拥有可以调用对象的抽象或虚拟方法。

一些示例代码基于您在问题中提出的内容:

public abstract class DocBase {
    ...
    public abstract void LoadProperties(IRepositoryRow row);
    ...
}

public List<T> GetDocs(){    

    var results = someService.GetMyDocuments();
    var documents = new List<T>();

    foreach(IRepositoryRow row in results) {
        var newDoc = new T();
        newDoc.LoadProperties(row);
        documents.Add(newDoc);    
    }
    return documents;
}