我有一个包含很多表的数据库,但大多数表具有相同的结构。它们都有一个
Id:int
列和一个 Name:string
列。
我正在编写 C# 类来表示这些表中的每个对象,但由于它们都有
Id, Name
,我决定让它们实现一个接口。
public interface IIdWithName
{
int Id { get; set; }
string Name { get; set; }
}
当我尝试在数据库中进行 CRUD 操作时,我最终复制了很多代码并且只更改了表名称。
我尝试让每个类继承具有
virtual TableName
的基类,但我无法使属性静态,并且让 TableName 的属性不是静态的没有意义,特别是对于以下情况我尝试从类中获取对象列表。
这是我尝试过的:
public class BaseClass : IIdWithName
{
public int Id { get; set; }
public string Name { get; set; }
public static string TableName { get; }
public static IEnumerable<IIdWithName> ReadAll()
{
string sql = $"select * from {TableName}";
// ... more code to read objects from db and return IEnumerable
}
}
public static SubClass1 : BaseClass
{
public static string TableName => "SubClass1TableName";
}
上面的代码编译得很好,但是当我尝试调用
SubClass1.ReadAll()
时,该方法会运行,但属性 TableName
没有设置为 SubClass1TableName
,而是 null
。
如何从基类继承,但仅覆盖静态属性?
如果这不是正确的做法,那么在这种情况下我可以做什么来减少重复的 CRUD 代码?
从 C# 11 开始,您可以使用 接口中的静态抽象方法 来实现类似的东西。例如:
public interface IIdWithName
{
// ...
static abstract string TableName { get; }
}
public abstract class BaseClass : IIdWithName
{
// ...
static string IIdWithName.TableName => throw new InvalidOperationException();
public static IEnumerable<T> ReadAll<T>() where T : IIdWithName
{
string sql = $"select * from {T.TableName}";
// ... more code to read objects from db and return IEnumerable
Console.WriteLine(sql);
return default;
}
}
public class SubClass1 : BaseClass, IIdWithName
{
public static string TableName => "SubClass1TableName";
}
用法如下:
var result = BaseClass.ReadAll<SubClass1>();
也许值得分离接口
IIdWithName
,这样BaseClass
就不必实现TableName
。
但我个人会考虑其他设计。可能只是使用像 Entity Framework 这样的 ORM,而不是编写自己的 ORM。