How to call a new method which is implemented in the concrete class of an interface
I am using structure map IOC container.
public interface ICompanyRepository
{
IEnumerable<Company> GetAll();
Company Get(int id);
Company Add(Company item);
bool Update(Company item);
bool Delete(int id);
}
public class CompanyRepository: ICompanyRepository
{
// Provide implementation for all interface methods
//Class CompanyRepository will also have the new method called DisplayLog
public void DisplayLog()
{
//To do
}
}
I am trying to implement DI using structure map in my Customer controller class
how can I tell the that I need methods ofcompany2 to be called?
_.Scan(x =>
{
x.TheCallingAssembly();
x.AddAllTypesOf<ICompanyRepository>();
// or
});
My code:
private readonly ICustomerRepository customerRepository;
public CustomerController(ICustomerRepository CustomerRepository)
{
customerRepository = CustomerRepository;
}
// GET: Customer
public ActionResult Index()
{
var customers = customerRepository.DisplayLog()
//Here i need to call CompanyRepository class methods DisplayLog() how can i call it here ?
// method DisplayLog() is not be shown here
return View(customers);
}
On an Interface, you can only call what is defined in the Interface - Its a definition of a "common base" of all classes that implement it. Ask yourself: What should happen if the ICompanyRepository you get is of a type that does NOT implement DisplayLog?
That means: It is not possible to call anything else than the interface methods right away.
To call DisplayLog on customerRepository there are 3 ways:
Add DisplayLog() to the Interface
Cast the customerRepository to CompanyRepository. but this will cause an exception, if the customerRepository is of any other type than CompanyRepository
Use a second interface
After all, I'm not quite sure if what you're doing is DI. In my understanding of DI it should be something like this:
public ActionResult Index(ILogDisplay display)
{
var customers = display.DisplayLog(customerRepository);
return View(customers);
}
ILogDisplay is being a new Interface for a separate class to be injected
public interface ILogDisplay
{
public YourResultType DisplayLog(ICustomerRepository);
}
In this example you actually inject a dependency (the implementation of ILogDisplay) in your class.
There's a couple of questions to raise here:
Why does the repository know how to display a log?
What does DisplayLog() mean in the context of a CustomerRepository?
Why should the controller even care about what the repository is logging?
Why is DisplayLog assigning a variable called customers when its return type is clearly void?
Fundamentally, the behaviour of your repository should be unknown to your controller, this is the essence of the Inversion of Control principle. All it cares about is that given the explicit contract provided by the interface for a repository, a method call will return customers. Logging is a concern of the repository.
A fairly traditional setup, from a DI point of view us the following:
ICompanyRepository:
public interface ICompanyRepository() {
IEnumerable<Company> GetAll();
Company Get(int id);
Company Add(Company item);
bool Update(Company item);
bool Delete(int id);
}
CustomerRepository:
public class CompanyRepository: ICompanyRepository
{
private readonly ILogger logger;
public CompanyRepository(ILogger logger) {
this.logger = logger;
}
// Provide implementation for all interface methods
public Company Get(int id) {
var customers = this.randomCustomerSource.Get(id);
this.logger.Info("Whatever you want to log here");
return customers;
}
}
CustomerController:
public class CustomerController {
private readonly ICustomerRepository customerRepository;
public CustomerController(ICustomerRepository CustomerRepository)
{
customerRepository = CustomerRepository;
}
// GET: Customers
public ActionResult Index()
{
var customers = customerRepository.GetAll()
return View(customers);
}
}
So the repository requests an Ilogger, the controller requests a ICompanyRepository, and will just call GetAll() and return the results. Usually there's a bit more involved but that's the very basic gist of a workflow for a controller that returns data.
Related
As I was trying to implement code first approach using repository patterns in MVC, I have come across some difficulties as below:
I have a Interface that have few methods declared as below :
public interface IRepository
{
User Getuserdetail(int UserId);
void Save(User Obj);
void delete(int Userid);
void update(User user);
}
Then I have a Repository class which could be using the above interface to define all the methods and will create a seperate layer of Entity Framework:
public class Repository : IRepository
{
RepoDBContext _context;
Repository(RepoDBContext Context)
{
this._context = Context;
}
public User Getuserdetail(int Userid)
{
var user = _context.User.Where(m => m.id == Userid).FirstOrDefault();
return user;
}
public void Save(User user)
{
_context.User.Add(user);
_context.SaveChanges();
}
}
Now could you please check the constructor of this class. The variable this constructor is initializing is type of "RepoDBContext" and the reference type it is using to assign it is also of "RepoDBContext". Is it internally performing like below?
RepoDBContext _context=new RepoDBContext();
My RepoDBContext class is below:
public class RepoDBContext : DbContext
{
public DbSet<User> User { get; set; }
}
Moreover if is the right way to perform then how will i have to call this class in my controller to do some functionality over my user interface. Please guide regarding the same and please don't mind my english. Thanks
I think you already have an answer to the question does assigning a parameter to a field is equivalent to instantiating a new instance of that type as state in the comments and in the answer by Oskar and Kirk.
But I just want go further and try to answer this another question of yours: how will I have to call this class in my controller to do some functionality over my user interface..
If you create your structure using the Repository pattern, you wouldn't want your controllers to handle instances of your DbContext class, because if they do, what is the benefit of having a separated repository layer then? A common pattern that I see people using and I use it myself in several apps is something as follows:
IUserRepository
public interface IUserRepository
{
User GetUserDetail(int userId);
void Save(User user);
void Delete(int userId);
void Update(User user);
}
UserRepository
public class UserRepository : IUserRepository
{
public User GetUserDetail(int userId)
{
using(var _context = new RepoDBContext())
{
return _context.User.Where(m => m.id == userId).FirstOrDefault();
}
}
//other implementations here..
}
Then, you create another layer which will be your Business layer, similar to the Repository.
IUserBusiness
public interface IUserBusiness
{
User GetUserDetail(int userId);
void Save(User user);
void Delete(int userId);
void Update(User user);
}
UserBusiness
public class UserBusiness : IUserBusiness
{
private readonly IUserRepository userRepository;
//CTOR receives a Repository instance via DI
public UserBusiness(IUserRepository userRepository)
{
this.userBusiness = userBusiness;
}
public User GetUserDetail(int userId)
{
//Call repository to get User details
return this.userRepository.GetUserDetail(userId);
}
//other implementations here
}
UserController (example)
public class UserController : Controller
{
private readonly IUserBusiness userBusiness;
//Controller receives a UserBusinnes instance via DI
public UserController(IUserBusiness userBusiness)
{
this.userBusiness = userBusiness;
}
public ActionResult GetDetail(int userId)
{
//Call your "repository" to get user data
var userDetail = userBusiness.GetUserDetail(userId);
//more logic here
}
}
See the difference? Each layer of your application is concerned with one thing. You controller request data to your business layer, which may apply some business rules or validations, and finally call your repository layer which knows how to talk to the database or other storage. Your controller doesn't have any concern about how to create instances of database class or make queries. It just receive a request, ask for data and returns back to the caller.
No, assigning an existing instance of RepoDBContext to a variable is NOT the same as calling new RepoDBContext(). Assignment is just assignment and will not allocate new objects.
Off-topic:
Please also consider that C# coding guidelines suggest that method parameters should be named likeThis (that is, with initial lower case letter). This will make you code more consistent with other .Net code libraries.
Dependency Inversion Principle states that higher level modules should not depend on lower level modules. Both should depend on abstractions. I do understand that principle. But as I'm using ASP.NET MVC, I often get my controller methods as:
public ActionResult MyAction(string userValue)
{
User user = MyDatabase.GetUser();
if (!user.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
user.Update(userValue);
return RedirectToAction("Success");
}
I believe this violates DIP because the result of my controller depends on the User class. In this scenario, I cannot think of a way of decoupling the Controller from my User class. Is there a way to get rid of this dependency? Or is this just fine to do it this way in this scenario?
create an interface and inject an implementation on that to your mvc controller.
public interface IMyDataAccess
{
User GetUser();
}
Create your implementation now.
public class MyMongoDBDataAccess : IMyDataAccess
{
public User GetUser()
{
//return a user from my fancy db
}
}
Now in your controller
public class HomeController : Controller
{
IMyDataAccess dao;
public HomeController(IMyDataAccess myDataAccess)
{
this.dao=myDataAccess;
}
public ActionResult MyAction(string userValue)
{
User user=this.dao.GetUser();
//return something to the view as needed.
}
}
You may use any dependency injection framework like Unity to inject the desired implementation of your interface to your controller.
If you want bring in more layers like Business Layer, Service layer, follow the same thing.
If your application structure is like below, than you are implementing DIP (Dependency Inversion Principle).
DIP says that a layer in your application should depend on a interface, not by an implementation. Like below, Service is depending on IDatabase not MyDatabase
public interface IDatabase {
Update(User user);
}
public interface MyDatabase : IDatabase
{
public Update(User user) {
// update user
}
}
public interface IService {
Update(string user);
}
public class Service : IService
{
private IDatabase _database;
public Service(IDatabase database)
{
_database = database;
}
public Update(User user) {
_database.Update(user);
}
}
DIP also says that high level modules like MvcController don't need to know/depend on low level modules, MyDatabase.
public class MvcController : Controller
{
private IService _service;
private IUserValidator _userValidator;
public MvcController(IService service, IUserValidator userValidator) // depending on abstraction
{
_service = service;
_userValidator = userValidator;
}
public ActionResult MyAction(string userValue)
{
if (!_userValidator.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
User user = _service.GetUser();
user.UserValue = userValue;
_service.Update(user);
return RedirectToAction("Success");
}
}
Note:
I recommend to take a look on 3-tier-architecture doing this you will improve your understanding of SOLID and your application will be more organized.
If in your case MyDatabase is a module Higher then User than, you are not respecting DIP principles, because your Controller make uses of a lower module.
DIP or IoC says High-level modules should not depend on low-level modules. Both should depend on abstractions.
It means that High Level class should not depend on concrete class but it should depend on Interface.
But here you are talking about User class which seems a DTO (Data Transfer Object).
So In that case, You must have to use that DTO in your last layer to either return data or deal with data.
But you should not be using POCO classes provided by entity framework, Instead you should create and use your DTO classes as ViewModels.
Ups, this is how I do it when using ASP.NET Web API, not sure if this works MVC Controller. But there is Unity.MVC (v3 or v4 or v5) lib (Unity.Mvc4) that you can use!
And you can wire it up like this, you should call this code in the Application_Start event!
public static class WebApiBootstrapper
{
public static void Init(IUnityContainer container)
{
GlobalConfiguration.Configure(config =>
{
config.DependencyResolver = new WebApiDependencyResolver(container); // DI container for use in WebApi
config.MapHttpAttributeRoutes();
WebApiRouteConfig.RegisterRoutes(RouteTable.Routes);
});
// Web API mappings
// All components that implement IDisposable should be
// registered with the HierarchicalLifetimeManager to ensure that they are properly disposed at the end of the request.
container.RegisterType<IYourController, YourController>(
new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(IMyDataBase)));
}
}
But before running tthis code you have to register the type mapping
container.RegisterType<IMyDatabse, MyDataBase>();
And you also have to implement the DependencyResolver class:
public class WebApiDependencyResolver : IDependencyResolver
{
protected IUnityContainer container;
public WebApiDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new WebApiDependencyResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
In your controller:
public class YourController : ApiController, IYourController
{
IDataBase _db;
public PlayGroundController(IDataBase db)
{
_db = db;
}
I am trying to use autofac with a repository and I am trying to add a little generics to try reducing the amount of duplicate code I am writing.However I am going round in circles trying to get autofac to work for me
So I created a domainservice and interface that handles our the standard crud operations
public class DomainService<T>:IDomainService<T>
{
protected readonly IDomainService<T> Repository;
public DomainService(IDomainService<T> repository)
{
Repository = repository;
}
public IQueryable<T> GetQueryable()
{
return Repository.GetQueryable();
}
public virtual Task<T> Add(T entity)
{
return Repository.Add(entity);
}
Interface:
public interface IDomainService<T>
{
IQueryable<T> GetQueryable();
Task<T> Add(T entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
Task<T> GetById(int id);
Task<T> GetByUID(Guid id);
}
I am using my repo is nothing special
public class SkillRepository : DomainService<Skill>, ISkill
{
private DataContext _db = new DataContext();
private readonly ILogger _log = null;
public SkillRepository(IDomainService<Skill> repository, ILogger log) : base(repository)
{
_log = log;
}
}
Finally where I wire up autofac:
var builder = new ContainerBuilder();
// Register the Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register other dependencies.
builder.Register(c => new Logger()).As<ILogger>().InstancePerApiRequest();
builder.RegisterType<SkillRepository>()
.As<IDomainService<Skill>>()
.As<ISkill>()
.InstancePerRequest();
// Build the container.
var container = builder.Build();
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
My web api controller looks like
public class SkillsController : BaseController<Skill>
{
private readonly ISkill _skillRepository;
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
{
_skillRepository = skillRepository;
}
}
BaseController
public abstract class BaseController<TEntity> : ApiController
where TEntity : new()
{
protected readonly IDomainService<TEntity> DomainService;
protected BaseController(IDomainService<TEntity> domainService)
{
DomainService = domainService;
}
I get an exception:
"None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'Api.EndPoints.Skills.SkillsController' can be invoked with the
available services and parameters:\ \ Cannot resolve parameter
'Domain.Repository.SkillRepository skillRepository' of constructor
'Void .ctor(Domain.Repository.SkillRepository)'."
Is there something obvious that I am doing wrong?
It cannot resolve the dependency because it's looking for the concrete type but you never registered SkillsRepository as that. Now you could change the registration to register the concrete type but that wouldn't be the best approach.
A better approach is to register SkillsRepository as its interfaces:
builder.RegisterType<SkillRepository>()
.As<ISkillsRepository>()
.InstancePerRequest();
And define ISkillsRepository to inherit all the other interfaces like ISkill that you want.
public interface ISkillsRepository : ISkill, IDomainService<Skill> { }
Don't register objects as concrete types and don't depend on concrete types in constructors.
public SkillsController(ISkillRepository skillRepository) :
base(skillRepository) ...
If you use concrete types as dependencies you create classes that cannot be tested using mocking frameworks.
Your use of SkillRepository : DomainService<Skill>, ISkill is perplexing too. Why is it both a skill and a domain service for skills? Doesn't make much sense.
Exception clearly states:
Cannot resolve parameter 'Domain.Interfaces.ISkill skillRepository' of constructor 'Void .ctor(Domain.IDomainService`1[Model.Skill], Domain.Interfaces.ISkill)'.
You have only IDomainService registered. But no ISkill (the line is commented).
Also why does the ctor require 2 parameters? SkillRepository implements both IDomainService<Skill> and ISkill so you should be able to pass it along:
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
P.S.
I'd name it this way:
public class SkillRepository : ISkillRepository, IDomainService<Skill>
And I prefer everything to be either plural (SkillsControllers, SkillsRepository) or everything singular (SkillController, SkillRepository).
In my opinion you should first sort out names for your classes which is making it hard to understand the code itself. secondly your repository is implementing domain service interface and ISkill and things like that is adding more confusion. i am pretty sure if you organise your classes properly then you will find solution to your problem.
For instance ApiController should use domain service, domain service should use repository and repository should deal with enties.
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(string name){}
public void DeleteSkillById(int id){}
..... etc
}
public class Repository:IRepository
{
public T Get(int id){}
public IEnumerable<T>GetAll(){}
}
Then you need to bind your interfaces to concrete classed in ioc. things should work that way i am pretty sure.
I am trying to use autofac with a repository and I am trying to add a little generics to try reducing the amount of duplicate code I am writing.However I am going round in circles trying to get autofac to work for me
So I created a domainservice and interface that handles our the standard crud operations
public class DomainService<T>:IDomainService<T>
{
protected readonly IDomainService<T> Repository;
public DomainService(IDomainService<T> repository)
{
Repository = repository;
}
public IQueryable<T> GetQueryable()
{
return Repository.GetQueryable();
}
public virtual Task<T> Add(T entity)
{
return Repository.Add(entity);
}
Interface:
public interface IDomainService<T>
{
IQueryable<T> GetQueryable();
Task<T> Add(T entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
Task<T> GetById(int id);
Task<T> GetByUID(Guid id);
}
I am using my repo is nothing special
public class SkillRepository : DomainService<Skill>, ISkill
{
private DataContext _db = new DataContext();
private readonly ILogger _log = null;
public SkillRepository(IDomainService<Skill> repository, ILogger log) : base(repository)
{
_log = log;
}
}
Finally where I wire up autofac:
var builder = new ContainerBuilder();
// Register the Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register other dependencies.
builder.Register(c => new Logger()).As<ILogger>().InstancePerApiRequest();
builder.RegisterType<SkillRepository>()
.As<IDomainService<Skill>>()
.As<ISkill>()
.InstancePerRequest();
// Build the container.
var container = builder.Build();
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
My web api controller looks like
public class SkillsController : BaseController<Skill>
{
private readonly ISkill _skillRepository;
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
{
_skillRepository = skillRepository;
}
}
BaseController
public abstract class BaseController<TEntity> : ApiController
where TEntity : new()
{
protected readonly IDomainService<TEntity> DomainService;
protected BaseController(IDomainService<TEntity> domainService)
{
DomainService = domainService;
}
I get an exception:
"None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'Api.EndPoints.Skills.SkillsController' can be invoked with the
available services and parameters:\ \ Cannot resolve parameter
'Domain.Repository.SkillRepository skillRepository' of constructor
'Void .ctor(Domain.Repository.SkillRepository)'."
Is there something obvious that I am doing wrong?
It cannot resolve the dependency because it's looking for the concrete type but you never registered SkillsRepository as that. Now you could change the registration to register the concrete type but that wouldn't be the best approach.
A better approach is to register SkillsRepository as its interfaces:
builder.RegisterType<SkillRepository>()
.As<ISkillsRepository>()
.InstancePerRequest();
And define ISkillsRepository to inherit all the other interfaces like ISkill that you want.
public interface ISkillsRepository : ISkill, IDomainService<Skill> { }
Don't register objects as concrete types and don't depend on concrete types in constructors.
public SkillsController(ISkillRepository skillRepository) :
base(skillRepository) ...
If you use concrete types as dependencies you create classes that cannot be tested using mocking frameworks.
Your use of SkillRepository : DomainService<Skill>, ISkill is perplexing too. Why is it both a skill and a domain service for skills? Doesn't make much sense.
Exception clearly states:
Cannot resolve parameter 'Domain.Interfaces.ISkill skillRepository' of constructor 'Void .ctor(Domain.IDomainService`1[Model.Skill], Domain.Interfaces.ISkill)'.
You have only IDomainService registered. But no ISkill (the line is commented).
Also why does the ctor require 2 parameters? SkillRepository implements both IDomainService<Skill> and ISkill so you should be able to pass it along:
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
P.S.
I'd name it this way:
public class SkillRepository : ISkillRepository, IDomainService<Skill>
And I prefer everything to be either plural (SkillsControllers, SkillsRepository) or everything singular (SkillController, SkillRepository).
In my opinion you should first sort out names for your classes which is making it hard to understand the code itself. secondly your repository is implementing domain service interface and ISkill and things like that is adding more confusion. i am pretty sure if you organise your classes properly then you will find solution to your problem.
For instance ApiController should use domain service, domain service should use repository and repository should deal with enties.
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(string name){}
public void DeleteSkillById(int id){}
..... etc
}
public class Repository:IRepository
{
public T Get(int id){}
public IEnumerable<T>GetAll(){}
}
Then you need to bind your interfaces to concrete classed in ioc. things should work that way i am pretty sure.
I'm trying to use Simple Injector to create my repository and use it in the Business logic layer ( also i want to use PerWebRequest method ) .
In the DAL layer i have :
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Delete(int id);
void Update(T entity);
T GetById(int Id);
IQueryable<T> All();
IEnumerable<T> Find(Func<T, bool> predicate);
}
and :
public class EFRepository<T> : IRepository<T>, IDisposable where T : class
{
#region Members
protected DbContext Context { get; set; }
protected DbSet<T> DbSet { get; set; }
#endregion
#region Constructors
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
Context = dbContext;
DbSet = Context.Set<T>();
}
and my context :
public class PASContext : DbContext, IDbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
public PASContext()
: base("PostAndSell")
{ }
}
As you can see EFRepository has only one constructor that takes one argument - this is because i want to use Simple Injector to create an instance of the context and pass it to the repository while it is created .
In the BLL i have a class ProductBLL and i want to get all products in that class (with some GetAll method) from the database and pass it, lets say to HomeController .
I really need someone to talk me through this .
I started by installing the right packages from the nuger (Simple Injector and Simple Injector ASP.NET Integration)
also in my global.asax.cs file, under Application_Start() function I`ve added :
var container = new SimpleInjector.Container();
container.RegisterPerWebRequest<IRepository<Product>, EFRepository<Product>>();
but where do i create the Context instance ? and how can i access it in the business layer ?
Since you will probably have many IReposotory<T> implementations (for Product, Customer, Employee, etc), it's better make a single open generic registration for IRepository<T> like this:
container.Register(typeof(IRepository<>), typeof(EFRepository<>), Lifestyle.Scoped);
Where the scoped lifestyle is defined as:
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
This registration ensures that Simple Injector will return a EFRepository<Product>, every time a IRepository<Product> is requested, an EFRepository<Customer> for IRepository<Customer>, and so on, and so on.
Since you want the same DbContext instance to be used over all repositories within the same request, you should also register the DbContext with the scoped Lifestyle:
container.Register<DbContext, PASContext>(Lifestyle.Scoped);
In the BLL i have a class ProductBLL and i want to get all products
from the database and pass it to, lets say HomeController
In that scenario, this ProductBLL seems like a useless abstraction to me. If all it does is passing data through, you can as easily let your HomeController depend on IRepository<Product> directly.