简体   繁体   中英

How to call new methods from a class which implements interface

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:

  1. Why does the repository know how to display a log?
  2. What does DisplayLog() mean in the context of a CustomerRepository?
  3. Why should the controller even care about what the repository is logging?
  4. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM