C#带有接口的泛型约束,用于解除API的耦合
本文关键字:用于 耦合 API 约束 接口 泛型 | 更新日期: 2023-09-27 18:13:15
在编写数据访问层时,我希望将面向公众的API与具体的数据库实现解耦。例如,假设我想使用MongoDb或Cassandra作为后备存储。
因此,我希望我的C#代码通过工厂方法等使用IThingDao。工厂将与实际实现相对应。
我有一些非常基本的接口和类示例来演示我希望实现的目标。不幸的是,这段代码生成了许多编译时错误,说这些类没有实现接口的成员。
以下定义了我的数据对象:
public interface IBase
{
Object Id { get; set; }
DateTime CreatedDate { get; set; }
}
public interface IBaseMongoDb : IBase
{
// Common MongoDb related things used by all concrete implementations
}
public interface IBaseCassandra : IBase
{
// Common Cassandra related things used by all concrete implementations
}
public interface IThing : IBase
{
String Name { get; set; }
}
public abstract class AbstractBase
{
public virtual Object Id { get; set; }
public DateTime CreatedDate { get; set; }
}
public abstract class AbstractMongoDbBase : AbstractBase
{
[BsonId]
public override Object Id { get; set; }
// Other specific MongoDb stuff
}
public abstract class AbstractCassandraBase : AbstractBase
{
// Cassandra related stuff
}
public class ThingMongoDbImpl : AbstractMongoDbBase, IThing, IBaseMongoDb
{
public String Name { get; set; }
}
public class ThingCassandraImpl : AbstractCassandraBase, IThing, IBaseCassandra
{
public String Name { get; set; }
}
MongoDb和Cassandra数据对象有单独的基本抽象,因为每个实现都有特定于一个和另一个的共同特性(如注释等(。
以下是数据访问接口:
public interface IDao<T>
{
T Save( T a_Value );
void Update( T a_Value );
void Delete( T a_Value );
T Find( Object a_Key );
}
public interface IThingDao : IDao<IThing>
{
IThing FindByName( String a_Name );
}
以下是MongoDb和Cassandra的实现:
public abstract class AbstractMongoDbDao<T> where T : IBaseMongoDb, new()
{
public T Save( T a_Value )
{
// Save
return a_Value;
}
public void Update( T a_Value )
{
// Update
}
public void Delete( T a_Value )
{
// Delete
}
public T Find( Object a_Key )
{
return new T();
}
}
public class ThingDaoMongoDbImpl : AbstractMongoDbDao<ThingMongoDbImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingMongoDbImpl();
}
}
public abstract class AbstractCassandraDao<T> where T : IBaseCassandra, new()
{
public T Save( T a_Value )
{
// Save
return a_Value;
}
public void Update( T a_Value )
{
// Update
}
public void Delete( T a_Value )
{
// Delete
}
public T Find( Object a_Key )
{
return new T();
}
}
public class ThingDaoCassandraImpl : AbstractCassandraDao<ThingCassandraImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingCassandraImpl();
}
}
对于此代码,ThingDaoMongoDbImpl和ThingDaoCasandraImpl生成以下编译时错误:
Error 1 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)'. 'generics.decouple.AbstractMongoDbDao<generics.decouple.ThingMongoDbImpl>.Find(object)' cannot implement 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)' because it does not have the matching return type of 'generics.decouple.IThing'.
Error 2 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Delete(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 95 18 Z
Error 3 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Update(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 95 18 Z
Error 4 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Save(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 95 18 Z
Error 5 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)'. 'generics.decouple.AbstractCassandraDao<generics.decouple.ThingCassandraImpl>.Find(object)' cannot implement 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)' because it does not have the matching return type of 'generics.decouple.IThing'.
Error 6 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Delete(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 126 18 Z
Error 7 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Update(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 126 18 Z
Error 8 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Save(generics.decouple.IThing)' C:'Projects'EDC'modules'EXCHANGES'CAD2CAD.Net'Z'Generics.cs 126 18 Z
关于如何实现这一点,有什么建议吗?
感谢
public class ThingDaoMongoDbImpl : AbstractMongoDbDao<ThingMongoDbImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingMongoDbImpl();
}
T Save( T a_Value ) { //implement it
}
void Update( T a_Value ) {
//implement it here
}
void Delete( T a_Value ) { // implement it here}
T Find( Object a_Key ) { //implement it}
}
由于您没有实现IThingDao
接口的方法,因此会出现编译时错误。你的public interface IThingDao : IDao<IThing>
,从IDao扩展而来,所以你必须实现IDao<IThing>
和的方法
更新
public class ThingCassandraImpl : AbstractCassandraBase, IThing, IBaseCassandra, IThingDao
{
public String Name { get; set; }
public IThing Save(IThing a_Value)
{
throw new NotImplementedException();
}
public void Update(IThing a_Value)
{
throw new NotImplementedException();
}
public void Delete(IThing a_Value)
{
throw new NotImplementedException();
}
public IThing Find(object a_Key)
{
throw new NotImplementedException();
}
public IThing FindByName(string a_Name)
{
throw new NotImplementedException();
}
}
public abstract class AbstractCassandraDao<T> where T : IBaseCassandra,IThingDao, new()
{
public T Save(T a_Value)
{
// Save
return a_Value;
}
public void Update(T a_Value)
{
// Update
}
public void Delete(T a_Value)
{
// Delete
}
public T Find(Object a_Key)
{
return new T();
}
}
public class ThingDaoCassandraImpl : AbstractCassandraDao<ThingCassandraImpl>
{
public IThing FindByName(String a_Name)
{
// Do the lookup and return value
return new ThingCassandraImpl();
}
public IThing Save(IThing a_Value)
{
throw new NotImplementedException();
}
public void Update(IThing a_Value)
{
throw new NotImplementedException();
}
public void Delete(IThing a_Value)
{
throw new NotImplementedException();
}
public IThing Find(object a_Key)
{
throw new NotImplementedException();
}
}