Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UnitOfWork & Generic Repository, SOLID principles with Custom Repository

I'm using UnitOfWork and Repository patterns in my project. I'm trying to code clean.

This is my IUnitOfWork.cs (Application Layer)

public interface IUnitOfWork : IDisposable
{
    int Save();
    IGenericRepository<TEntity> Repository<TEntity>() where TEntity : class;
}

The implementation UnitOfWork.cs : (Persistence Layer)

public class UnitOfWork : IUnitOfWork
{      
    private readonly DBContext _context;
    private Hashtable _repositories;
    public UnitOfWork(DBContext context)
    {
        _context = context;
    }

    public IGenericRepository<T> Repository<T>() where T : class
    {
        if (_repositories == null)
            _repositories = new Hashtable();

        var type = typeof(T).Name;

        if (!_repositories.ContainsKey(type))
        {
            var repositoryType = typeof(GenericRepository<>);

            var repositoryInstance =
                Activator.CreateInstance(repositoryType
                    .MakeGenericType(typeof(T)), _context);

            _repositories.Add(type, repositoryInstance);
        }

        return (IGenericRepository<T>)_repositories[type];
    }

    public int Save()
    {
        // Save changes with the default options
        return _context.SaveChanges();
    }

    // etc.. Dispose()
}

My IGenericRepository.cs : (Application Layer)

public interface IGenericRepository<TEntity>
    where TEntity : class
{
    void Update(TEntity entity);
    void Delete(object id);
    void InsertList(IEnumerable<TEntity> entities);
    // etc..
}

In my service : (Application Layer)

var result = UnitOfWork.Repository<Entities.Example>().Delete(id);

And using Unity, I inject the dependency in the container.

  container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager())

And it works like a charm.

Now I have a custom Repository ICustomRepository:

public interface ICustomRepository: IGenericRepository<Entities.Custom>
{
    void Test();
}

How can I access the Test() function using my IUnitOfWork?

var result = UnitOfWork.Repository<Entities.Custom>().Test();  // not working

UPDATE:

@Thomas Cook give me a way using cast :

   (UnitOfWork.Repository<Entities.Custom>() as ICustomRepository).Test();

I get a NullReferenceException:

System.NullReferenceException: 'Object reference not set to an instance of an object.'
like image 551
Zied R. Avatar asked Nov 06 '22 07:11

Zied R.


1 Answers

You'll have to cast, because UnitOfWork Repository method returns a IGenericRepository which doesn't declare Test. So you'll need to cast the returned value to a ICustomRepository which inherits IGenericRepository and bolts on the Test method.

like image 116
Thomas Cook Avatar answered Nov 09 '22 23:11

Thomas Cook