简体   繁体   English

如何正确接口现有的密封类?

[英]How to correctly interface an existing sealed class?

After having my code being reviewed on CodeReview, I am stuck on the question how to make my piece of code more abstract. 在CodeReview上检查了我的代码之后,我陷入了一个问题,即如何使我的代码片段更加抽象。

As you can see in here , many suggest that I should create an ICommand and IConnection interface to make it easier to refactor. 如您在这里看到的,许多建议我应该创建一个ICommandIConnection接口,以使其易于重构。

In my examples I will only use IConnection , but the whole should also be valid for ICommand . 在我的示例中,我将仅使用IConnection ,但整个过程对于ICommand也应有效。

I figured I would have to create an interface like this; 我认为我必须创建一个这样的接口;

public interface IConnection
{
     //etc...
}

And then, to make the MySqlConnection be able to inherit from my IConnection , I would have to create my own MySqlConnection which would inherit like this; 然后,为了使MySqlConnection能够从我的IConnection继承,我必须创建自己的MySqlConnection ,它会像这样继承;

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

Which would mean the new MySqlConnection would still have its methods and fields, and would inherit from IConnection . 这意味着新MySqlConnection仍然有其方法和字段, 会继承IConnection I should then be able to write a Database class like this; 然后,我应该能够编写这样的Database类;

public abstract class Database
{
    protected IConnection con;
}

And extend it like this; 并像这样扩展它;

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

Now, my problem is, MySqlConnection is sealed ; 现在,我的问题是, MySqlConnectionsealed I can't extend it and therefore I do not know any option to make this database class abstract. 我无法扩展它,因此我不知道使该数据库类抽象的任何选择。

The question is; 问题是; is there a proper way to implement the abstraction of Database and if yes, how would I do it? 有没有适当的方法来实现Database的抽象?如果是,我该怎么做?

Please note that this question has nothing to do with the class being a singleton (as shown in my CodeReview post). 请注意 ,此问题与类为单例无关(如我的CodeReview帖子中所示)。 That problem has been issued and is not relevant to the question. 该问题已经发布,与该问题无关。

Reading the comments on that code review, I actually think they meant use IDbConnection and IDbCommand instead of rolling your own. 阅读有关代码审查的评论,我实际上认为它们的意思是使用IDbConnectionIDbCommand而不是自己动手。 All ADO.NET providers already implement those. 所有ADO.NET提供程序都已经实现了这些功能。

However if you want you could inherit from DbConnection and IConnection and wrap the MySqlConnection . 但是,如果您愿意,可以继承DbConnectionIConnection包装 MySqlConnection You'd have to implement all DbConnection methods and relay them to the wrapped connection: 您必须实现所有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();
    }

    // ...

What about implementing decorator pattern: 如何实现装饰器模式:

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

Then you can create a class like this: 然后,您可以创建一个这样的类:

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
}

So what do you achive like this: 所以你会这样实现:

1) you can explicitly expose those fields of Connection class that you really need 1)您可以显式公开您真正需要的Connection类的那些字段

2) you still can make initial configuration at the stage of initialization of your concrete Database class 2)您仍然可以在具体的Database类的初始化阶段进行初始配置

3) and your code becomes some kind of more abstract 3),您的代码变得更加抽象

4) and what is very convenient - if connections for different databases (fe mysql/sqlite and so on) will have different names of connectionString field - then you can wrap them with your single property, defined by your interface. 4)什么是非常方便的-如果不同数据库的连接(例如mysql / sqlite等)将具有不同的connectionString字段名称-那么您可以使用接口定义的单个属性包装它们。 What I mean - you are the one to rule the situation, and inheritance might limit you at this point. 我的意思是-您是掌管局势的人,继承在这一点上可能会限制您。

Anyway, before starting to implement something, try to describe everything with interfaces and only then implement classes. 无论如何,在开始实现某些东西之前,请尝试使用接口描述所有内容,然后才实现类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM