Search code examples
architecturerepositoryfactory-patterndecoupling

Decoupling the Dal Repository using the Factory pattern


I'm trying to decouple the Bll from the Dal using some interfaces and a Factory patter. Data.Contracts containing the interfaces will be referenced on my Bll.

This is a small test code:

class Program
{
    static void Main(string[] args)
    {
        IDataRepositoryFactory _DataRepositoryFactory;
        IUserRepository userRepository = _DataRepositoryFactory.GetDataRepository<IUserRepository>();
     }
}


public abstract class RepositoryBase<T> where T : class, new() { }
public class UserRepository : RepositoryBase<User>, IUserRepository 
{
    public UserRepository() { }
}

public class DataRepositoryFactory : IDataRepositoryFactory
{
    public T GetDataRepository<T>() where T : IDataRepository, new()
    {
        return ObjectBase.Container.GetExportedValue<T>();
    }
}

public class User 
{
    public int Id { get; set; }
}

public abstract class ObjectBase
{
    public ObjectBase() { }

    public static CompositionContainer Container { get; set; }

}

public interface IDataRepository { }

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

public interface IUserRepository : IDataRepository { }

public interface IDataRepositoryFactory
{
    T GetDataRepository<T>() where T : IDataRepository, new();
}

An finally I got my error:

'Data.Contracts.IUserRepository' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Data.Contracts.IDataRepositoryFactory.GetDataRepository()'

My question is: Which is the correct implementation to Decouple the code on the Business layer using the factory pattern? I can not use the concrete implementation UserRepository since it inherits from classes that I do not want in the BLL.

Any help would be appreciated.


Solution

  • From the code perspective you should just disable "new" constraint on factory interface:

    public interface IDataRepositoryFactory
    {
        T GetDataRepository<T>() where T : IDataRepository; //, new();
    }
    
    public class DataRepositoryFactory : IDataRepositoryFactory
    {
        public T GetDataRepository<T>() where T : IDataRepository//, new()
        {
            return ObjectBase.Container.GetExportedValue<T>();
        }
    }
    

    From the design point of view repositories look a bit complicated:

    For me IDataRepository (non-generic) and RepositoryBase seem redundant, but that depends of the exact case (probably you didn't provide enough details). I'd use IDataRepository<T> -> IUserRepository:IDataRepository<User> -> UserRepository inheritance chain.

    Also it's not clear what types belong to BLL.

    For example, this breakdown looks all right to me:

    • BLL:
      • User
      • IUserRepository:IDataRepository<User>
    • DAL/Infrastructure:
      • IDataRepositoryFactory
      • IDataRepositoryFactory:IDataRepositoryFactory
      • IDataRepository<T>
      • UserRepository

    In general I'd suggest to simplify code structure and start with the simplest possible way, then adding new interfaces/classes when you really need them.