TrackableEntities / trackable-entities

N-Tier Support for Entity Framework with WCF or ASP.NET Web API
http://trackableentities.github.io
MIT License
120 stars 36 forks source link

Please introduce RepositoryFactory Pattern in UnitOfWork Implementations #146

Open noufionline opened 8 years ago

noufionline commented 8 years ago

Hi Tony,

First of all, Kudos for your excellent contribution to the community.

Wouldn't it be nice if we introduce RepositoryFactory Pattern and Inject only that in the UnitOfWork Constructor.

So instead of this

  public NorthwindUnitOfWork(INorthwindSlimContext context,
            ICustomerRepository customerRepository,
            IOrderRepository orderRepository) :
            base(context as DbContext)
        {
            _customerRepository = customerRepository;
            _orderRepository = orderRepository;
        }

Something like this

  public NorthwindUnitOfWork(INorthwindSlimContext context,
            IRepositoryFactory repositoryRepository) :
            base(context as DbContext)
        {
            _repositoryRepository = repositoryRepository;
        }

  public ICustomerRepository CustomerRepository
        {
            get { return _repositoryRepository.GetRepository<ICustomerRepository>() ; }
        }

        public IOrderRepository OrderRepository
        {
            get { return _repositoryRepository.GetRepository<IOrderRepository>() ; }
        }

 public class RepositoryFactory : IRepositoryFactory
    {
        private readonly IContainer _container;

        public RepositoryFactory(IContainer container)
        {
            _container = container;
        }
        public T GetRepository<T>()
        {
            return _container.GetInstance<T>();
        }
    }

in this way we can avoid injecting all the repositories from the constructor.

tonysneed commented 8 years ago

@noufionline Thanks for the suggestion. Can you provide a sample implementation? Feel free to fork the repo, create a branch, and submit a pull request. Sounds like a good idea.

noufionline commented 8 years ago

Sure! But the only change required must be a single interface which will provide a Generic Method Retrieve/Create desired Repository.

public interface IRepositoryFactory
{
     T GetRepository<T>();
}

and this interface must be injected in your Unit Of Work class

public NorthwindUnitOfWork(INorthwindSlimContext context,
            IRepositoryFactory repositoryRepository) :
            base(context as DbContext)
        {
            _repositoryRepository = repositoryRepository;
        }

The implementation of this interface should be left to users who might prefer to create the repository using reflection or a prefred container, or may be a default implementation can be provided with a concrete base class which can be overriden by the user.

in my case I prefer to use my container to resolve the requested repository.

By doing this only the required repository will be created and can avoid unncessery creation of all the repositories even when only one or two is used.

If you can do this in your T4 Template then all the repository can be created using this factory.

tonysneed commented 8 years ago

@noufionline Thanks, I'll have a look at putting the interface into the Patterns lib. Not sure if I currently have the bandwidth to update the UoW template, but I can look into that.

I noticed you opened a PR #148 -- is there a reason why you closed it?

noufionline commented 8 years ago

I am creating a pull request for the first time and was confused a lil bit. Now I have two pull requests don't know how to delete my own code.

But it's a good beginning anyways :)

tonysneed commented 8 years ago

What you want to do is to a) fork the TE repo, b) create a local branch, c) commit your changes to the local branch you created, d) publish your branch, e) create a new pull request. Hope that helps.

noufionline commented 8 years ago

Thanks a lot for your tips. :) It really helped.

noufionline commented 8 years ago

Created a pull request #149 to address this issue.