Question

I don't know how manage properly the interfaces in C#. My goal is to have an abstract class for my Business Layer Services that have some common methods (like Save(), Dispose()), that call different DAL repository methods. I wish to avoid to repeat in all my services something like:

public Save() 
{
   repository.Save();
}

I have a scenario similar to that:

Interface

namespace Common
{
    public interface IRepository
    {
        void Save;
        void Dispose;
    }
}

DAL

namespace DAL
{
    public Repository : IRepository
    {
        public void Save() {};
        public void Dispose() {};
        public void Add() {}
    }
}

BL

namespace BL
{
    public abstrac BaseService
    {
        protected IRepository repository;
        protected BaseService(IRepository repo)
        {
            repository = repo;
        }

        public Save() 
        {
            repository.Save();
        }
    }

    //...

    //Tentative 1
    public Service : BaseService
    {
        private Repository rep;

        public Service()
            : base(new DAL.Repository())
        {
            rep = base.repository; // ERROR: cannot convert IRepository to Repository
        }
    }
}

I tried also this:

//Tentative 2
public Service : BaseService
{
    private IRepository rep;

    public Service()
        : base(new DAL.Repository())
    {
        rep = base.repository; // OK
    }

    public void Add()
    {
        rep.Add() // ERROR: IRepository doesn't contain a definition for 'Add'
    }
}

I know I could define in the interface all the methods I want to use, but I'll will have to manage a lot of problems with generic types and, as you should have understand from my question, I'm quite new in C# and I wish to avoid complexity is is possible, utill I'll be more expert at least :)

Was it helpful?

Solution 2

public Service()
        : base(new DAL.Repository())
    {
           rep = (Repository)base.repository;

    }

This way u will get the Add() service which is not a part of IRepository but a newer implementation in the extended class.

OTHER TIPS

Firstly I think you're having a name clash with you member IRepository rep.

Try using DAL.IRepository rep

The reason that you're getting an error is that you've defined "Add" as something unique to "Repository". Your member variable is an "IRepository" allowing you to put anything that implements "IRepository" onto it.

Just because you CAN put a Repository into it, doesn't mean that everything on it is going to be a repository. (Think of it look good 'ol fingers and thumbs, all thumbs are fingers, but not all fingers are thumbs)

If you NEED to call add on any repository, then add it to the interface. Else, you need to decide whether or not that member should be IRepository or Repository.

Alternatively, you COULD use

    Repository myRep = rep as Repository;
    if(rep!=null)
    {
       myRep.Add();
       ...
       profit();
    }

Seeing as your main problem is the lack of accessibility to the Add method, and seeing as this is a relative common method anyway, I would firstly recommend adding it to your IRepository, so it looks like this:

public interface IRepository
{
    void Add();
    void Save();
    void Dispose();
}

You would then implement your appropriate repositories whilst inheriting from IRepository. Now, understandably you may want to be able to access custom methods on a Repository. In order to resolve this what you could do is have your BaseService accept a generic repository:

public BaseService<T> where T : IRepository
{
    protected T repository { get; set; }
    protected BaseService(T repo)
    {
        repository = repo;
    }
}

Then a service would look like this

public UserService : BaseService<UserRepository>
{
    public UserService() : base(new DAL.UserRepository())
    {
        // base.Repository is now a UserRepository.
    }    
}

With this implementation your UserService will be able to access all of the methods that UserRepository exposes, as it's strongly typed with the generic. Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top