如何为常量定义基类或接口?

时间:2017-05-29 12:24:02

标签: c# oop interface

在我的应用程序中,我需要为多个类定义一组相同的常量值,并且我想使用它们的一个基类/接口作为我的泛型类的类型参数。

//I know following code will not work, just trying to demonstrate the problem
public interface IConstantsDefined
{
    static const string DbName;
    static const string TableName;
    static const string ColumnName;
}

public static class Product : IConstantsDefined
{
    public static const string DbName = "ProductDB";
    public static const string TableName = "Products";
    public static const string ColumnName = "ProductId";
}

public static class Sales: IConstantsDefined
{
    public static const string DbName = "SalesDb";
    public static const string TableName = "Sales";
    public static const string ColumnName = "SaleId";
}

public class DbConnection<TConsts> where TConsts : IConstantsDefined
{
// use TConsts.DbName, TConsts.TableName here
}

我明白我上面写的内容会在C#中引发很多错误。我知道静态类不能从接口继承。我的问题是,构建这样一个系统的最佳设计/方法是什么,记住性能和内存?

3 个答案:

答案 0 :(得分:2)

常量被定义并初始化一次。

public interface IConstantsDefined
{
    static const string Foo = "Foo";
    static const string Bar = "Bar";
}

你想要的是抽象的get-only字段:

public interface IConstantsDefined
{
    string DbName { get };
    string TableName { get };
    string ColumnName { get };
}

public class Product : IConstantsDefined
{
    public string DbName { get { return "ProductDB" } };
    public string TableName { get { return "Products" } };
    public string ColumnName { get { return "ProductId" } };
}

public class Sales: IConstantsDefined
{
    public string DbName { get { return "ProductDB" } };
    public string TableName { get { return "Sales" } };
    public string ColumnName { get { return "SaleId" } };
}

由于您不需要/想要产品和销售类型的多个实例,您可能需要考虑完全删除类型,因为这几乎是类的定义:

public class ConstantsDefined
{
    public string DbName { get; private set; };
    public string TableName { get; private set; };
    public string ColumnName { get; private set; };

    public static readonly ConstantsDefined Product = new ConstantsDefined()
    {
        DbName = "ProductDB",
        TableName = "Products",
        ColumnName = "ProductId",
    };
}

答案 1 :(得分:0)

您可以在@nabuchodonossor的评论中尝试。或者,您可以创建实现接口IMetadata的元数据类,ProductMetadata和SalesMetadata。然后在需要时,您可以通过传入实际的模型信息(例如,typeof(Sales))来使用工厂来获取元数据实例。

答案 2 :(得分:0)

最接近想要的是使用基本抽象类:

abstract class Base
{
    public abstract string DbName { get; }
}
class Product : Base
{
    public override string DbName => "ProductDB";
}
class Sales : Base
{
    public override string DbName => "SalesDB";
}
class DbConnection<T> where T : Base
{
    public string Test(T instance) => instance.DbName;
}

这确实需要instance,可由DbConnection保留,由服务提供商等解决。

  

我的所有产品或销售类都有各种常量,所以我不想创建这些实例

这个要求基本上改变了一切。您似乎将给定上下文中的常量理解为“无法更改的值”。哪个是不可变的类型。那么你不需要泛型来构造带有常量的类型,只需传递参数(就像你对任何不可变类型那样):

class DbConnection
{
    public string DbName { get; }

    public DbConnection(string dbName)
    {
        DbName = dbName;
    }
}

用法:您只需new DbConnection<Product>()而不是神秘的new DbConnection("ProductDB")。如果你有多个参数,那么考虑包装它们并将实例传递给构造函数。这就是我在第一个代码段中最终得到抽象类和非静态继承的地方:new DbConnection(new Product())(而DbConnection需要Base类型才能通过)。