Reputation: 211
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);
}
Upvotes: 0
Views: 171
Reputation: 5900
There's a couple of questions to raise here:
DisplayLog()
mean in the context of a CustomerRepository?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.
Upvotes: 1
Reputation: 109
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:
DisplayLog()
to the InterfaceAfter 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.
Upvotes: 1