簡體   English   中英

如何在基類中定義可以在泛型方法中調用的靜態變量?

[英]How do I define a static variable in base class that can be called in generic methods?

我有一個非常復雜的關系數據庫,這使我一遍又一遍地使用相同的代碼。 我正在嘗試使用相當復雜的TableRow類對其進行清理,但是遇到了一個主要問題。 我可以解釋我要做什么的最好方法是通過一些示例代碼:

public abstract class TableRow
{
    public abstract string TableName { get; }
    public abstract string PrimaryKey { get; }

    //there's a lot of these sort of methods for multi-to-multi links, links by two columns, etc
    protected T GetLinkedRow<T>() where T : TableRow
    {
        //here I need to get TableName and PrimaryKey (without creating a new instance of T)
    }
 }

 public class Person : TableRow
 {
    public override string TableName { get { return "People"; } }
    public override string PrimaryKey { get { return "PersonID"; } }
 }

 public class Dog : TableRow
 {
    public override string TableName { get { return "Dogs"; } }
    public override string PrimaryKey { get { return "DogID"; } }

    public Person GetOwner() { return GetLinkedRow<Person>(); }
 }

現在,我意識到這不是實現我想要實現的目標的方法,因為我可以創建一個類,其類具有TableName或PrimaryKey的變量值,但我不打算這樣做。 我希望能夠覆蓋靜態屬性,但是我知道這是不可能的。 我以前在每個表上都有一個類,但這意味着有70個相當無用的類,而這正是我要避免的。 解決此類問題的更好方法是什么?

更新:

最終,我將繼續創建T的新實例以獲取TableName,因為無論如何我都將初始化新實例。 盡管SLaks的解決方案遠勝於此,但它不能保證派生類具有TableName和PrimaryKey屬性。 對於大多數人來說,SLaks的解決方案將更合適,因此我將其標記為可接受的答案。

protected T GetLinkedRow<T>() where T : TableRow, new()
{
    T row = new T();
    DbDataReader reader = ExecuteReader("SELECT * FROM [" + row.TableName + "] WHERE [" + this.PrimaryKey + "] = " + this.ID);
    if(!reader.Read())
        throw new Exception("No linked row found");
    row.Load(reader);
    return row;
}

//here's the reason I didn't really want to do this in the first place. Many-to-many relationship. quite messy
protected IEnumerable<T> GetLinkedRows<T>(string junctionTable) where T : TableRow, new()
{
    T row = new T();
    DbDataReader reader = ExecuteReader("SELECT * FROM [" + row.TableName + "] INNER JOIN [" + junctionTable + "] ON [" + row.TableName + "].[" + row.PrimaryKey + "] = [" + junctionTable + "].[" + row.PrimaryKey + "] WHERE [" + junctionTable + "].[" + this.PrimaryKey + "] = " + this.ID;
    while(reader.Read()) {
        row.Load(reader);
        yield return row;
        if(reader.HasRows)
            row = new T();
    }
}

如果沒有實例,則完全不可能調用虛擬方法( get_TableName )。

相反,您可以在類上使用屬性,然后調用typeof(T).GetCustomAttributes(typeof(YourAttribute), false)

根據更新的信息...

何必呢? 為什么不只使用定義方法“ GetLinkedRow”的抽象方法(或者更好的接口),具體實現可以在其中提供詳細信息。

也就是說,您知道到Dog的鏈接行將始終是Person,因此您具有接口(警告:未編譯!)

public interface ILinkedRow
{
    public TableRow GetLinkedRow();
}

然后Dog具有以下實現:

public class Dog : TableRow, ILinkedRow
{
    //Implementation here

    public TableRow GetLinkedRow()
    {
        Person p = //implement method
        return p
    }
}

您的處理代碼可以忽略返回的行是Person的事實(如果它永遠不需要知道),或者將其(Person)myDog.GetLinkedRow();(Person)myDog.GetLinkedRow();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM