Reputation: 2120
After having my code being reviewed on CodeReview, I am stuck on the question how to make my piece of code more abstract.
As you can see in here, many suggest that I should create an ICommand
and IConnection
interface to make it easier to refactor.
In my examples I will only use IConnection
, but the whole should also be valid for 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;
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
. I should then be able to write a Database
class like this;
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
; 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?
Please note that this question has nothing to do with the class being a singleton (as shown in my CodeReview post). That problem has been issued and is not relevant to the question.
Upvotes: 2
Views: 2197
Reputation: 1576
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
2) you still can make initial configuration at the stage of initialization of your concrete Database
class
3) and your code becomes some kind of more abstract
4) and what is very convenient - if connections for different databases (f.e. 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. 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.
Upvotes: 0
Reputation: 26446
Reading the comments on that code review, I actually think they meant use IDbConnection
and IDbCommand
instead of rolling your own. All ADO.NET providers already implement those.
However if you want you could inherit from DbConnection
and IConnection
and wrap the MySqlConnection
. You'd have to implement all DbConnection
methods and relay them to the wrapped connection:
public sealed class MyMySqlConnection : DbConnection, IConnection
{
public MyMySqlConnection(MySqlConnection underlyingConnection)
{
UnderlyingConnection = underlyingConnection;
}
public MySqlConnection UnderlyingConnection
{
get;
private set;
}
public override void Open()
{
UnderlyingConnection.Open();
}
// ...
Upvotes: 4