如何在基类中定义可以在泛型方法中调用的静态变量

本文关键字:调用 静态 变量 泛型方法 基类 定义 | 更新日期: 2023-09-27 17:56:53

我有一个极其复杂的关系数据库,这导致我一遍又一遍地使用相同的代码。我正在尝试使用一个相当复杂的 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();