出于我的目的,我有一个基于数据库的对象的基类(不完全是这样,但为了清楚起见,我们保持这种方式)。
所有派生类都需要一个TableName
成员,其中包含数据库表的名称
我需要的是一种满足以下所有要点的方法:
以下函数适用于所有派生类:
List<T> ReadAll<T>() where T: BaseClass, new()
{
List resultList = new List();
var results = doQuery("SELECT * FROM " + T.TableName);
foreach (var r in results)
{
resultList.Add(new T(r));
}
return resultList;
}
(从表中读取所有记录 - 需要表名)
每当我创建一个新的派生类时,基类的继承需要强制我添加/覆盖TableName成员,否则代码不应该编译(无论如何都是它的目的之一);
< / LI> TableName
成员应该是静态的(或者那个目的),因为我不需要派生类型的“假”实例只是为了点而访问常量成员1。
现在,假设我的目的是明智的而不是基于错误的假设,我怎样才能达到所有这些目的,考虑到(出于好的理由)C#不允许继承静态成员?
如果您认为我错误地认为所有要点应该可以一起实现,您认为我应该如何改变我的设计?
答案 0 :(得分:1)
你不能覆盖静态成员,因此为了每个类的不同而拥有一个静态字段通常是行不通的。如果您需要每个类的此类数据,那么您谈的是元数据,可以使用属性创建
[AttributeUsage(AttributeTargets.Class)]
public class TableNameAttribute : Attribute
{
private readonly string _name;
public string Name {get { return _name; } }
public TableNameAttribute(string name) { _name = name; }
}
然后在每个班级
[TableName("Derived")]
public class DerviedClass { /*...*/ }
但是,这在编译时无法解决,因此当给定类中不存在[TableName]
时,您需要确保添加正确的处理。如果你需要被迫总是确保属性存在,那就写一些好的单元测试,也许noe会扫描你的程序集并检查所有被正确标记的类型,或者遵循“所有代码必须在执行之前运行一次”规则。请注意,通过良好实践和测试在运行时强制执行此操作,您还可以更轻松地避免错误表格名称的不可避免的麻烦。
使用属性,除非您编写静态属性来访问表名属性,否则不会需要将泛型约束为单数类型。
答案 1 :(得分:0)
您不需要静态成员来强制每个类要求&#34; TableName&#34;成员 - 只需将其作为一个抽象属性:
public abstract class BaseClass
{
public abstract string TableName {get;}
}
public class DerivedClass : BaseClass
{
public override string TableName {get {return "Derived";} }
}
使abstract
强制继承类来实现属性 - 无论是使用静态属性,常量,只读属性还是其他东西都可以使用它们。
答案 2 :(得分:0)
这里有两个问题:
两者的解决方案是拥有一个位置,例如包含将类名映射到表名的字典。然后,每个派生类都可以在其构造函数中从BaseClass
调用以下受保护方法,以获取它们自己的表名:
protected string TableName()
{
return ClassTableMappings.GetTableName(this.GetType().Name);
}