Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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# 按接口返回特定存储库_C# - Fatal编程技术网

C# 按接口返回特定存储库

C# 按接口返回特定存储库,c#,C#,我有如下代码结构。我目前有两个存储库类,到目前为止,它们都使用单个方法实现了一个通用接口。它们只传递不同的返回类型对象。我还有Factory模式类来检索特定的存储库。我的问题在我的RepositoryFactory中,我收到如下所示的错误消息。老实说,我不知道该怎么办。指望你的支持 错误: public interface IRepository<T> where T :class { IEnumerable<T> GetRecords(); } public

我有如下代码结构。我目前有两个存储库类,到目前为止,它们都使用单个方法实现了一个通用接口。它们只传递不同的返回类型对象。我还有Factory模式类来检索特定的存储库。我的问题在我的RepositoryFactory中,我收到如下所示的错误消息。老实说,我不知道该怎么办。指望你的支持

错误:

public interface IRepository<T> where T :class 
{
   IEnumerable<T> GetRecords();
}

public class CsvRepository : IRepository<InputData>
{

   private string _path;

   public CsvRepository(string path)
   {
       _path = path;
   }

   public IEnumerable<IBasic> GetRecords()
   {
       return from line in File.ReadLines(_path)
              select line.Split(',') into parts
              where parts.Length == 3
              select new InputData { Name = parts[0], X = Convert.ToInt32(parts[1]), Y = Convert.ToInt32(parts[2]) };
    }
}

//other repositories:
public class OracleRepository : IRepository<OtherDataType>
{
..
}
...


//Factory pattern to get specific repository on demand
//Implement IoC later on (register instead of cases)
public class RepositoryFactory
{
   public static IRepository GetRepository(DataSource repositoryType)
   {
      IRepository repo;
      switch (repositoryType)
      {       
         //break;
         case DataSource.Csv:
              repo = new CsvRepository("path"); //perhaps path shoudln't br right passed right here - so where?
              break;
         case DataSource.Oracle:
              repo = new OracleRepository();
              break;
         default:
              throw new ArgumentException("Invalid Repository Type");
      }

   return repo;
   }
}

代码:

public interface IRepository<T> where T :class 
{
   IEnumerable<T> GetRecords();
}

public class CsvRepository : IRepository<InputData>
{

   private string _path;

   public CsvRepository(string path)
   {
       _path = path;
   }

   public IEnumerable<IBasic> GetRecords()
   {
       return from line in File.ReadLines(_path)
              select line.Split(',') into parts
              where parts.Length == 3
              select new InputData { Name = parts[0], X = Convert.ToInt32(parts[1]), Y = Convert.ToInt32(parts[2]) };
    }
}

//other repositories:
public class OracleRepository : IRepository<OtherDataType>
{
..
}
...


//Factory pattern to get specific repository on demand
//Implement IoC later on (register instead of cases)
public class RepositoryFactory
{
   public static IRepository GetRepository(DataSource repositoryType)
   {
      IRepository repo;
      switch (repositoryType)
      {       
         //break;
         case DataSource.Csv:
              repo = new CsvRepository("path"); //perhaps path shoudln't br right passed right here - so where?
              break;
         case DataSource.Oracle:
              repo = new OracleRepository();
              break;
         default:
              throw new ArgumentException("Invalid Repository Type");
      }

   return repo;
   }
}
因此:

然而,我得到了错误:

Cannot implicitly convert type 'CsvRepository' to 'IRepo'. An explicit conversion exists (are you missing a cast?)  
Cannot implicitly convert type 'SqlRepository' to 'IRepo'. An explicit conversion exists (are you missing a cast?)  

您可以为您的数据再添加一个抽象级别,以便在泛型中使用新的抽象:

public interface IBasic { }

public class InputData : IBasic { }

public class OtherDataType : IBasic { }
现在,您的IRepository应该针对IBasic接口编写

public interface IRepository<T> where T : IBasic
{
    IEnumerable<T> GetRecords();
}
公共接口假定,其中T:IBasic
{
IEnumerable GetRecords();
}
现在,您可以具体实现上述假设:

public class CsvRepository : IRepository<IBasic>
    {

        private string _path;

        public CsvRepository()
        {
            var filename = ConfigurationManager.AppSettings["CSVFileName"];
            _path = AppDomain.CurrentDomain.BaseDirectory + filename;
        }

        public IEnumerable<IBasic> GetRecords()
        {
            _path = "Read path";
            //Implement Yield & iterator here !!
            throw new NotImplementedException();
        }
    }

    //other repositories:
    public class OracleRepository : IRepository<IBasic>
    {

        private string _path;

        public OracleRepository()
        {
            var filename = ConfigurationManager.AppSettings["CSVFileName"];
            _path = AppDomain.CurrentDomain.BaseDirectory + filename;
        }

        public IEnumerable<IBasic> GetRecords()
        {
            _path = "Read path";
            //Implement Yield & iterator here !!
            throw new NotImplementedException();
        }
    }
公共类CsvRepository:IRepository
{
私有字符串路径;
公共CsvRepository()
{
var filename=ConfigurationManager.AppSettings[“CSVFileName”];
_路径=AppDomain.CurrentDomain.BaseDirectory+文件名;
}
公共IEnumerable GetRecords()
{
_path=“读取路径”;
//在这里实现Yield和iterator!!
抛出新的NotImplementedException();
}
}
//其他存储库:
公共类OracleRepository:IRepository
{
私有字符串路径;
公共或公共场所
{
var filename=ConfigurationManager.AppSettings[“CSVFileName”];
_路径=AppDomain.CurrentDomain.BaseDirectory+文件名;
}
公共IEnumerable GetRecords()
{
_path=“读取路径”;
//在这里实现Yield和iterator!!
抛出新的NotImplementedException();
}
}
现在,您的工厂看起来是这样的:

 public class RepositoryFactory
    {
        public static IRepository<IBasic> GetRepository(DataSource repositoryType)
        {
            IRepository<IBasic> repo = null;
            switch (repositoryType)
            {

                //break;
                case DataSource.Csv:
                    repo = new CsvRepository();
                    break;
                case DataSource.Oracle:
                    repo = new OracleRepository();
                    break;
                default:
                    throw new ArgumentException("Invalid Repository Type");
            }

            return repo;
        }
    }
公共类存储工厂
{
公共静态IRepository GetRepository(DataSource repositoryType)
{
i预期回购=空;
开关(repositoryType)
{
//中断;
案例数据源.Csv:
回购=新的CsvRepository();
打破
案例数据源。Oracle:
回购=新的OracleRepository();
打破
违约:
抛出新ArgumentException(“无效存储库类型”);
}
回购回报;
}
}

我相信您的目标是拥有一个存储库,但要有多个实现。然后您要选择其中一个实现

public interface IRecordRetrieverRepository<out TModel> : IDisposable
{
     IEnumerable<TModel> RetrieveAllRecords();
}
我们已经定义了我们的工厂接口

public class RecordRetrieverFactory<TContext, TModel> : IRecordRetrieverFactory
{
     public TRecordRetrieverRepository BuildContext() => new TContext<TModel>();
}
公共类RecordRetrieverFactory:IRecordRetrieverFactory
{
public TRecordRetrieverRepository BuildContext()=>new TContext();
}
然后您可以简单地执行以下语法

using(var context = new RecordRetrieverFactory<ExcelContext, SampleModel>().BuildContext())
     return context.RetrieveAllRecords();
使用(var context=new RecordRetrieverFactory().BuildContext())
返回context.RetrieveAllRecords();

在不丢失表达代码的情况下提供了一点灵活性。我没有验证或测试代码,写得很快,但应该可以工作。不过,有些反射可能被忽略了。

IRepository
是一种通用类型。如果不指定泛型类型,就不能声明它。@BJMyers-ye我知道,但是这个接口用于不同的存储库。我应该创建特殊的非T-generic接口并在所有存储库中实现,以便能够在Factory模式方法中使用我的存储库,还是有更合适的方法?或者其他方法,如IRepository-->IRepository:IRepository和在工厂中使用IRepository方法?不确定。@BJMyers查看了我在编辑子句中的主要帖子,我到目前为止一直在尝试什么。@最后一个帖子:您认为如何将路径传递到CsvRepository的ctor中-目前我在GetRepository方法中有它,但我认为这不是一个好方法,应该在哪里传递它呢?其他信息也会传递到其他存储库。在当前的解决方案中,对象是在GetRepository方法中创建的,所以这意味着在ctorts中,所有这些都将存在——请给出建议,因为我不认为getfactory不适合这样做。顺便说一下,我还需要通过GetRepository参数传递这些信息。。。不好看起来很好,让我先检查一下(不会忘记马克作为答案)。顺便问一下,你能告诉我另外一件事吗,为什么我试着从我的主要帖子的编辑部分给出提到的错误?如果你能提供额外的答案,我将不胜感激。谢谢@JimmyJimm:我看不出你的抽象有任何问题。我添加了更多的代码,我想这足以说明为什么我会出现下面这一错误:repo=new CsvRepository();repo=newsqlrepository();(请注意,我谈论的是我的编辑主博文部分代码。如果在OracleRepository函数public IEnumerable GetRecords()中,我想实现Yield…只要函数不知道要定义为return的确切类型,如何实现它?查看新内容:从File.ReadLines(_settings.Path)中的行返回)选择line.Split(',')到parts.Length==3的部分,选择new InputData{X=Convert.ToInt32(parts[1]),Y=Convert.ToInt32(parts[2]);但InputData应该是IBasic,然后无法正确设置ctor参数。。。
public class ExcelContext<TModel> : IRecordRetrieverRepository<TModel>
{
     public IEnumerable<TModel> RetrieveAllRecords()
     {
         // Actual implementation.
     }
}
public interface IRecordRetrieverFactory
{
     TRecordRetrieverRepository BuildContext();
}
public class RecordRetrieverFactory<TContext, TModel> : IRecordRetrieverFactory
{
     public TRecordRetrieverRepository BuildContext() => new TContext<TModel>();
}
using(var context = new RecordRetrieverFactory<ExcelContext, SampleModel>().BuildContext())
     return context.RetrieveAllRecords();