J’ai rencontré aujourd’hui un problème et je me demande si je m’y prends bien pour le coup.
J’ai créé une interface (IPersistanceContext) qui présente une méthode CreateConnection() ayant un type de retour assez générique : System.Data.IDbConnection (c’est un exemple, j’ai d’autres méthodes qui retournent d’autres interfaces).
J’ai créé ensuite une classe (SqlPersistanceContext) implémentant cette interface, et fonctionnant pour SQL Server 2000. Le but de l’interface est que quelqu’un d’autre pourra créer la même chose pour Oracle par ex.
Dans le cas de SQL2k, je créé un objet SqlConnection et je le retourne (SqlConnection implémente l’interface IDbConnection).
[code]public interface IPersistanceContext
{
System.Data.IDbConnection CreateConnection();
}
public class SqlPersistanceContext : IPersistanceContext
{
public System.Data.IDbConnection CreateConnection()
{
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connectionString);
return conn;
}
}[/code]
J’utilise ma classe SqlPersistanceContext dans un premier temps au travers d’un objet Factory (du pattern du même nom) qui me retourne un IPersistanceContext.
IPersistanceContext context = Factory.GetContext();
IDBConnection connexion = context.CreateConnection();
Aucun souci donc, je m’attends bien à avoir un IDbConnection retourné par ma méthode.
Dans un second temps, étant donné que ma classe SqlPersistanceContext est utilisée par une autre classe prévue pour fonctionner avec SQL Server 2000 uniquement, elle appelle la méthode CreateConnection() en s’attendant bien à obtenir un SqlConnection.
SqlPersistanceContext context = new SqlPersistanceContext();
SqlConnection connexion = (SqlConnection)context.CreateConnection();
Avec ce code, je suis obligé de transtyper le IDbConnection retourné en SqlConnection.
Mais du coup, je me suis dit que je pourrais très bien retourner directement un objet SqlConnection, vu qu’il implémente l’interface IDbConnection, ma méthode retourne bien (indirectement) un IDbConnection.
Si je fais cela, le compilo me sors une erreur comme quoi SqlPersistanceContext n’implémente pas le membre d’interface CreateConnexion() (type de retour différent).
Code qui ne compile pas :
[code]public class SqlPersistanceContext : IPersistanceContext
{
public System.Data.SqlClient.SqlConnection CreateConnection()
{
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connectionString);
return conn;
}
}[/code]
Ce qui me chagrine, c’est que SqlConnection implémente bien l’interface IDbConnection.
Il semblerait qu’on ne puisse pas appliquer le « qui peut le plus peut le moins » : Définir une méthode retournant une classe implémentant une interface A ne signifie pas que l’on implémente une méthode retournant cette même interface A.
La seule solution semble être de passer par du boxing dans les endroits où je sais que j’obtiendrais un SqlConnection. N’y a-t-il pas d’autre solution ? Est-ce que j’ai fait une erreur dans la conception même de mes classes ? Quelle est la justification d’une telle limitation dans le compilateur C# (ou dans l’IDL ?) ?
J’espère que j’ai été suffisament clair