如何正确对接现有的密封类

本文关键字:密封类 何正确 | 更新日期: 2023-09-27 18:25:22

在CodeReview上审阅了我的代码后,我一直在思考如何使我的代码更加抽象。

正如您在这里看到的,许多人建议我应该创建一个ICommandIConnection接口,以使重构更容易。

在我的例子中,我将只使用IConnection,但整体也应该对ICommand有效。

我想我必须创建一个这样的界面;

public interface IConnection
{
     //etc...
}

然后,为了使MySqlConnection能够从我的IConnection继承,我必须创建我自己的MySqlConnection,它将像这样继承;

public class MySqlConnection : MySql.Data.MySqlClient.MySqlConnection, IConnection
{
     //etc...
}

这意味着新的MySqlConnection仍将有其方法和字段,将继承自IConnection。然后,我应该能够像这样编写一个Database类;

public abstract class Database
{
    protected IConnection con;
}

并像这样扩展它;

public class MySqlDatabase : Database
{
    private override IConnection con = new MySqlConnection();
}

现在,我的问题是,MySqlConnection就是sealed;我不能扩展它,因此我不知道有什么选项可以使这个数据库类抽象。

问题是;有没有合适的方法来实现Database的抽象?如果有,我将如何实现?

请注意这个问题与类是否为singleton无关(如我的CodeReview帖子中所示)。这个问题已经提出,与这个问题无关。

如何正确对接现有的密封类

阅读关于代码审查的评论,我实际上认为它们意味着使用IDbConnectionIDbCommand,而不是自己滚动。所有ADO.NET提供程序都已经实现了这些。

但是,如果需要,可以从DbConnectionIConnection继承,并包装MySqlConnection。您必须实现所有DbConnection方法,并将它们中继到封装的连接:

public sealed class MyMySqlConnection : DbConnection, IConnection
{
    public MyMySqlConnection(MySqlConnection underlyingConnection)
    {
        UnderlyingConnection = underlyingConnection;
    }
    public MySqlConnection UnderlyingConnection
    {
        get;
        private set;
    }
    public override void Open()
    {
        UnderlyingConnection.Open();
    }
    // ...

实现装饰器模式:

interface IConnection
{
    string ConnectionString {get; set;} // Define your interface explicitly
}

然后你可以创建这样一个类:

class MySqlDbConnection : IConnection
{
    private MySql.Data.MySqlClient.MySqlConnection connection;
    public MySqlConnection(MySql.Data.MySqlClient.MySqlConnection connection)
    {
        // Check for null
        this.connection = connection;
    }
    #region Implementation of IConnection
    public ConnectionString
    {
        get
        {
            return connection.ConnectionString; // Not sure if this is the right name of property
        }
        set
        {
            connection.ConnectionString = value;
        }
    }
    #endregion
}

那么你得到了什么:

1) 您可以显式地公开Connection类中真正需要的字段

2) 您仍然可以在具体Database类的初始化阶段进行初始配置

3) 你的代码变成了某种更抽象的

4) 非常方便的是,如果不同数据库(如mysql/sqlite等)的连接将有不同的connectionString字段名称,那么您可以用接口定义的单个属性来包装它们。我的意思是,你是统治局面的人,而继承可能会在这一点上限制你。

无论如何,在开始实现某个东西之前,试着用接口描述所有东西,然后才实现类。