Decoupling the Dal Repository using the Factory pattern

500 views Asked by At

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.

1

There are 1 answers

1
mikalai On BEST ANSWER

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.