Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型约束与接口解耦API_C#_Generics - Fatal编程技术网

C#泛型约束与接口解耦API

C#泛型约束与接口解耦API,c#,generics,C#,Generics,在编写数据访问层时,我希望将面向公共的API与具体的db实现分离。例如,假设我想使用MongoDb或Cassandra作为我的备份存储 所以,我想要的是我的C#代码通过一个工厂方法等来利用iTingDao。工厂将与实际实现相对应 我有一些非常基本的接口和类示例来演示我希望实现的功能。不幸的是,这段代码生成了大量编译时错误,表示类没有实现接口的成员 以下内容定义了我的数据对象: public interface IBase { Object Id { get; set; } Dat

在编写数据访问层时,我希望将面向公共的API与具体的db实现分离。例如,假设我想使用MongoDb或Cassandra作为我的备份存储

所以,我想要的是我的C#代码通过一个工厂方法等来利用iTingDao。工厂将与实际实现相对应

我有一些非常基本的接口和类示例来演示我希望实现的功能。不幸的是,这段代码生成了大量编译时错误,表示类没有实现接口的成员

以下内容定义了我的数据对象:

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 );
}
公共接口IDao
{
T保存(T a_值);
无效更新(T a_值);
无效删除(T a_值);
找不到(对象a_键);
}
公共接口:IThingDao:IDao
{
i使用FindByName(字符串a_名称);
}
以下是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();
    }
}
公共抽象类AbstractMongoDbDao,其中T:IBaseMongoDb,new()
{
公共T保存(T a_值)
{
//拯救
返回一个_值;
}
公共无效更新(T a_值)
{
//更新
}
公共无效删除(T a_值)
{
//删除
}
公共找不到(对象a_键)
{
返回新的T();
}
}
公共类thingdaomgodbimpl:AbstractMongoDbDao,IThingDao
{
public-IThing-FindByName(字符串a_名称)
{
//执行查找并返回值
返回新的ThingMongoDbImpl();
}
}
公共抽象类AbstractCassandrado,其中T:IBaseCassandra,new()
{
公共T保存(T a_值)
{
//拯救
返回一个_值;
}
公共无效更新(T a_值)
{
//更新
}
公共无效删除(T a_值)
{
//删除
}
公共找不到(对象a_键)
{
返回新的T();
}
}
公共类ThingDaoCassandraImpl:AbstractCassandrado,IThingDao
{
public-IThing-FindByName(字符串a_名称)
{
//执行查找并返回值
返回新内容cassandraimpl();
}
}
对于此代码,ThingDaoMongoDbImpl和ThingDaoCassandraImpl生成以下编译时错误:

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
错误1“generics.decouple.ThingDaoMongoDbImpl”未实现接口成员“generics.decouple.IDao.Find(object)”。”generics.decouple.AbstractMongoDbDao.Find(对象)“无法实现”generics.decouple.IDao.Find(对象)”,因为它没有匹配的返回类型“generics.decouple.IThing”。
错误2“generics.decouple.ThingDaoMongoDbImpl”未实现接口成员“generics.decouple.IDao.Delete(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 95 18 Z
错误3“generics.decouple.ThingDaoMongoDbImpl”未实现接口成员“generics.decouple.IDao.Update(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 95 18 Z
错误4“generics.decouple.ThingDaoMongoDbImpl”未实现接口成员“generics.decouple.IDao.Save(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 95 18 Z
错误5“generics.decouple.ThingDaoCassandraImpl”未实现接口成员“generics.decouple.IDao.Find(object)”。”generics.decouple.AbstractCassandrado.Find(对象)“无法实现”generics.decouple.IDao.Find(对象)”,因为它没有匹配的返回类型“generics.decouple.IThing”。
错误6“generics.decouple.ThingDaoCassandraImpl”未实现接口成员“generics.decouple.IDao.Delete(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 126 18 Z
错误7“generics.decouple.ThingDaoCassandraImpl”未实现接口成员“generics.decouple.IDao.Update(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 126 18 Z
错误8“generics.decouple.ThingDaoCassandraImpl”未实现接口成员“generics.decouple.IDao.Save(generics.decouple.IThing)”C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\generics.cs 126 18 Z
有什么建议可以让它工作吗


谢谢

这里有很多似乎不正确的地方,这对于一个简单的答案来说可能太宽泛了。例如,在
AbstractMongoDbDao
类中,方法获取并返回参数T,该参数仅限于
ibasMongoDB
。这就是你的意思吗?要保存并返回一个
IBaseMongoDb
?或者您想要像
公共TValue保存(TValue value){…}
?@RonBeyer谢谢您的回答。是的,我想用IBaseMongoDb进行约束,因为这些数据对象中有特定于MongoDb的东西,比如BSON注释。我看到了很多重复的代码
IBase->IBaseMongoDb
AbstractBase->AbstractMongoDbBase
都具有相同的属性,在
ThingMongoDbImpl
中实现和描述。你不知道是什么让你这么做的吗?但这些重复是可以避免的。当你有抽象类时,也要避免在
接口中使用属性。谢谢你的回答。这两个抽象道都有你所指的方法。这就是为什么我把它们放在抽象类中,所有其他子类都会自动获取它们。那不对吗?不,不对。查看我的更新。必须实现接口
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}
}
  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();
        }
    }