我正在研究一個非常簡單的框架,我想在其中自動執行CRUD功能。爲了這個問題的目的,我創建了下面的代碼,簡單來說明我的問題。獲取抽象類中定義的屬性值
所有項目都從(抽象)基類「DbItem」(包含CRUD函數)派生而來,其中子類提供了附加功能,並且還定義了存儲DbItems的表名。例如,「設備」和「實體」都源自DbItem,並定義表名(分別爲「設備」和「實體」)。然而,「實體」類是抽象的,並且進一步由「人類」和「動物」類派生。 (所有的人類和動物都存儲在共享的「實體」表中,但設備存儲在單獨的表中)。在DbItem中定義的Save()方法正確地解析了DbTable屬性。
然而,我也有一個DbCollection類,它擴展了泛型C#集合類。我希望DbCollection能夠通過反射自動確定正確的數據庫表名。因此,如果我想創建一個所有設備的列表,我創建一個新的DbCollection,並且該代碼組成相應的SELECT語句(SELECT ... FROM設備...)。這工作。
但是,如果我想要一個所有實體(動物和人類)的列表,我有一個問題。 「實體」被標記爲抽象的,我不應該能夠實例化它。但是,我也不知道如何獲取Entity.DbTable屬性的值。
一個簡單的「修復」是從Entity類定義中刪除限定的「abstract」。然而,這聽起來並不正確。
你能告訴我如何獲得Entity.DbTable屬性的值嗎?
class Program
{
abstract class DbItem
{
public int Id { get; set; }
public abstract string DbTable { get; }
public void Save()
{
Console.WriteLine($"INSERT INTO {DbTable} (Id) VALUES ({this.Id})...");
}
}
abstract class Entity : DbItem
{
public sealed override string DbTable { get => "entities"; }
}
class Human : Entity { }
class Equipment : DbItem
{
public override string DbTable => "equipment";
}
class DbCollection<T> : System.Collections.ObjectModel.Collection<T>
{
public virtual string DbTable { get
{
Type t = typeof(T);
//System.Reflection.PropertyInfo p = t.GetProperty("DbName");
if(t.IsAbstract)
{
// What do we do here to get the value of Entity.DbTable?
var prop = t.GetProperty("DbTable");
// Herein lies the problem: One cannot instantiate an abstract class to provide to the GetValue() method
return prop.GetValue(null).ToString(); // System.Reflection.TargetException: 'Non-static method requires a target.'
}
else
{
var obj = Activator.CreateInstance(t);
//return (obj as DbItem).DbTable; // this also works
var prop = t.GetProperty("DbTable");
return prop.GetValue(obj).ToString();
}
}
}
public DbCollection()
{
Console.WriteLine($"SELECT Id FROM {DbTable} WHERE ...");
}
}
static void Main(string[] args)
{
var h = new Human();
h.Save(); // 1. Correctly outputs "entities";
var e = new Equipment();
e.Save(); // 2. Correctly outputs "equipment";
var ec = new DbCollection<Equipment>(); // 3. Correctly outputs "equipment"
var hc = new DbCollection<Human>(); // 4. Correctly outputs "entities"
var entityCollection = new DbCollection<Entity>(); // 5. Error.
Console.ReadLine();
}
}
你是指什麼:去除抽象不適合你?爲什麼它必須是抽象類?你能解釋一下這個需求嗎? – bhuvin
既然永遠不會有一個實體不會是人或動物,我會認爲「實體」應該是抽象的。 除了特定於人類和動物(以及僅在相應類別中定義的)之外,我使用「實體」來包含人類和動物共享的一些屬性/方法(例如名稱,地址...)。 因此,我理解將實體標記爲抽象概念上是正確的。 但是如果情況並非如此,那麼我想刪除「抽象」將是最好的選擇:)。 – Ziggga
您正在尋找'static'成員。一個'[Attribute]'也是合理的。 –