简体   繁体   English

具有接口的C#泛型约束以解耦API

[英]C# Generics Constraints with Interfaces to Decouple an API

In writing a data access layer, I want to decouple my public facing API from the concrete db implementations. 在编写数据访问层时,我想将面向公众的API与具体的数据库实现分离。 For example, let's suppose that I want to use either MongoDb or Cassandra for my backing store. 例如,假设我要对我的后备存储使用MongoDb或Cassandra。

So, what I want is for my C# code to utilize IThingDao through a factory method, etc. The factory will correspond to the actual implementation. 因此,我想让我的C#代码通过工厂方法等利用IThingDao 。工厂将与实际实现相对应。

I have some very rudimentary interface and class samples to demonstrate what I hope to achieve. 我有一些非常基本的界面和类示例来演示我希望实现的目标。 Unfortunately for me, this code generates numerous compile time errors saying the classes don't implement the members of the interface. 对我来说不幸的是,这段代码产生了许多编译时错误,这些错误表明类未实现接口的成员。

The following define my data objects: 以下定义了我的数据对象:

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; }
}

There are separate base abstracts for MongoDb and Cassandra data objects because each implementation has common features (such as annotations, etc) specific to one versus the other. MongoDb和Cassandra数据对象有单独的基本摘要,因为每种实现都有一个特定于另一种的共同特征(例如注释等)。

Here are the data access interfaces: 这是数据访问接口:

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 );
}

Here are the implementations for MongoDb and Cassandra: 这是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();
    }
}

For this code, ThingDaoMongoDbImpl and ThingDaoCassandraImpl generate the following compile time errors: 对于此代码, ThingDaoMongoDbImplThingDaoCassandraImpl生成以下编译时错误:

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

Any suggestions on how to get this working? 关于如何使它工作的任何建议?

Thanks 谢谢

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}
}

You are getting the compile time error because you did not implement the method of IThingDao interface. 因为没有实现IThingDao接口的方法, IThingDao遇到了编译时错误。 your public interface IThingDao : IDao<IThing> , extends from IDao so you have to implement the methods of IDao<IThing> also 您的public interface IThingDao : IDao<IThing>从IDao扩展而来,因此您还必须实现IDao<IThing>的方法

UPDATE 更新

  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();
        }
    }

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

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