简体   繁体   English

如何从实现接口的类中调用新方法

[英]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. 如何调用在接口的具体类中实现的新方法我正在使用结构映射IOC容器。

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? 我正在尝试在我的Customer控制器类中使用结构映射来实现DI,如何告诉我需要调用company2的方法?

_.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 ? 问问自己:如果您获得的ICompanyRepository类型不实现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: 要在customerRepository上调用DisplayLog ,有3种方法:

  • Add DisplayLog() to the Interface DisplayLog()添加到接口
  • Cast the customerRepository to CompanyRepository. 将customerRepository强制转换为CompanyRepository。 but this will cause an exception, if the customerRepository is of any other type than CompanyRepository 但是,如果customerRepository是CompanyRepository以外的任何其他类型,则将导致异常
  • Use a second interface 使用第二个界面

After all, I'm not quite sure if what you're doing is DI. 毕竟,我不确定您正在做的是DI。 In my understanding of DI it should be something like this: 在我对DI的理解中,应该是这样的:

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 ILogDisplay是要注入的单独类的新接口

public interface ILogDisplay 
{
    public YourResultType DisplayLog(ICustomerRepository);
}

In this example you actually inject a dependency (the implementation of ILogDisplay) in your class. 在此示例中,您实际上在类中注入了一个依赖项(ILogDisplay的实现)。

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? DisplayLog()在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? 当DisplayLog的返回类型明显无效时,为什么要为其分配一个称为客户的变量?

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: 从DI的角度来看,这是一个相当传统的设置,我们可以:

ICompanyRepository: ICompany资料库:

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: 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. 因此,存储库请求一个Ilogger ,控制器请求一个ICompanyRepository ,并将只调用GetAll()并返回结果。 Usually there's a bit more involved but that's the very basic gist of a workflow for a controller that returns data. 通常涉及的内容更多,但这是返回数据的控制器的工作流程的最基本要点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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