2014-10-03 2 views
1

После проверки моего кода на CodeReview, я застрял в вопросе, как сделать мою часть кода более абстрактной.Как правильно связать существующий закрытый класс?

Как вы можете видеть в here, многие предлагают создать интерфейс ICommand и IConnection, чтобы упростить рефакторинг.

В моих примерах я буду использовать только 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, и если да, как бы я это сделал?

Обращаем внимание, что этот вопрос не имеет ничего общего с тем, что класс является одноэлементным (как показано в моем сообщении CodeReview). Эта проблема была выпущена и не имеет отношения к этому вопросу.

+1

Я не думаю, что есть «правильный путь»; существует несколько способов. Мой первый вопрос будет тем, что будет целью IConnection. Что означает, что IDbConnection нет? –

+0

Рекомендуемая точка вместо использования объекта concreate Connection, определенного для провайдера, с помощью интерфейса IConnection при создании соединения, так что завтра, если вы переходите на другого провайдера, вам не нужно делать какие-либо крупные изменения в вашем коде – Thangadurai

+2

Is not что к чему IDBConnection (предоставляется каркасом) должен/должен быть? И, как я полагаю, MySqlConnection также реализует? –

ответ

3

Считая комментарии к этому обзору кода, я на самом деле думаю, что они имели в виду использование IDbConnection и IDbCommand вместо того, чтобы кататься самостоятельно. Все провайдеры ADO.NET уже реализуют эти.

Однако, если вы хотите, вы можете наследовать от DbConnection и IConnection и обертки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(); 
    } 

    // ... 
+0

Самый верный ответ там даже упоминает IDbConnection во второй своей отметке. Я думаю, что это был предназначенный совет. –

+0

Вы совершенно правы. Я много думал о парне, который сказал мне использовать «IConnection» и забыл проверить другие ответы. Наверное, я плохой. Использование 'IDbConnection' работает так, как предполагается. Спасибо за обходной путь, который вы предоставили в любом случае, могут быть полезны в будущем! –

0

насчет реализации decorator шаблона:

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) и что очень удобно - если соединения для разных баз данных (fe mysql/sqlite и т. д.) будут иметь разные имена полей connectionString - тогда вы можете обернуть их своим единственным свойством, определенным вашим интерфейсом. Что я имею в виду - вы правы, и наследование может ограничить вас на этом этапе.

В любом случае, прежде чем приступать к реализации, попробуйте описать все с помощью интерфейсов и только затем реализовать классы.

Смежные вопросы