具有类型T的通用构造函数的通用存储库

时间:2015-01-30 01:54:27

标签: c# generics repository

我在c#中有以下课程:

public class Customer{
  public long Id { get; set;}
  public String Firstname { get; set;}
  public String Lastname { get; set;}

  public Customer(long id, String firstname, String lastname){...}
}

public class Book{
  public long Id { get; set;}
  public String Title { get; set;}
  public String Author{ get; set;}
  public int NumberOfCopies{ get; set;}

  public Book(long id, String title, String author, int numberofcopies){...}
}

我的存储库是通用的,界面如下:

public interface IGenericRepository<T> where T : class, new(){

  Add(T entity);
  Update(T entity);
  Delete(T entity);
  GetAll();

}

因此,要为Customer创建存储库,我将创建一个IGenericRepository&lt; Customer&gt;和书籍IGenericRepository&lt; Book&gt;。要从GUI访问这些方法,我需要一个方法,如:AddCustomer(long id,String firstname,String lastname)和一本书的相同,因为GUI不知道实体本身。我在想创建一个包含这些方法的CustomerService和BookService。 但是,我必须为我添加的每个实体创建一个新的服务。

我的问题是,如何使这项服务具有通用性,并仍然保留实体构造函数中的参数?

要说清楚,我想要一个通用的Service类,它可以添加书籍和客户,但使用相同的方法。例如:

Add(<constructor parameters of T>)

将从Controller类调用此方法,该类将具有所有服务。然后,GUI可以通过控制器访问这些服务方法。

这可能吗?如果有,怎么样?如果不是,有没有更好的解决方案来实现这一目标?

提前致谢!

4 个答案:

答案 0 :(得分:1)

一种选择是根据需要接受参数,例如: G:

public void Add<T>(params object param) { ... }

T是您要创建的类型。通过反射检查哪些构造函数可用,选择适合参数列表的构造函数。然后实例化对象。瞧。

答案 1 :(得分:0)

我会将IRepository<t>方法Add(T entity)更改为Add(object entity)。这样,您就可以为任何实体使用完全相同的代码。

答案 2 :(得分:0)

我通常看到它完成的方式是你有以下内容:

1。 定义通用添加,更新,删除等的接口:

public interface IGenericRepository<T> where T : class
{
    Add(T entity);
    Update(T entity);
    Delete(T entity);
    GetAll();
}

2。 一个通用存储库,它接受您将持久保存到数据存储的不同类型。

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    private connectionInformation;

    public GenericRepository<T>(object connectionInformation)
    {
        // do something with the connection info, dbContext, etc...
    }

    public T Add(T entity)
    {
        // implementation...
    }

    public T Update(T entity)
    {
        // implementation...
    }

    public T Delete(T entity)
    {
        // implementation...
    }

    public List<T> GetAll()
    {
        // implementation...
    }
}

3。 一个工作单元,用于为不同的具体类型设置通用存储库的实例。

public class UnitOfWork
{
    private object connectionInformation;

    public UnitOfWork(object connectionInformation)
    {
        // set up your connection information
        this.connectionInformation = connectionInformation;

        this.CustomerRepository = new GenericRepository<Customer>(connectionInformation);

        this.BookRepository = new GenericRepository<Book>(connectionInformation);
    }

    public GenericRepository<Book> BookRepository { get; private set; }

    public GenericRepository<Customer> CustomerRepository { get; private set; }
}

4。 可以实例化工作单元的服务/服务层&#34;你可以与之互动。它是负责处理每种类型的不同属性的服务,但数据保存和检索将通过unitOfWork处理。在您的服务中,您可以使用以下方法:

public void DeleteFirstBook()
{
    var unitOfWork = new UnitOfWork(connnectionInformation);

    var books = unitOfWork.BookRepository.GetAll();

    if(books.Any())
    {
        unitOfWork.BookRepository.Delete(books.First());
    }
}

您也可以为客户执行相同的操作。使服务层到位可以帮助您的代码过于紧密耦合。 &#34;数据层&#34;应该只负责与数据库交互(创建,读取,更新,删除)。如您所述,您的UI层也应该不知道如何创建新对象或与数据库交互。因此,服务变得很重要,因为它知道如何设置数据,在何处放置数据,以及如何将数据返回到UI。

希望它有所帮助!

答案 3 :(得分:0)

相当标准的方法是将“创建者”委托传递给您的存储库,我也不确定它是否符合您的目标:

public interface IGenericRepository<T> where T : class{

  Add(Func<T> creator);
  ...
}

Repository<T> : IGenericRepository<T> where T : class
{
     public  Add(Func<T> creator) 
     {
        T newOne = creator();
        ....
     }
}

// usage
bookRepository.Add(() => new Book(42, "some title", ...));