首页 > 解决方案 > 有没有办法实现适配器或接口而不更改在这种情况下使用它的类?

问题描述

我正在尝试学习和理解接口、适配器和依赖注入以及如何使用它们来实现抽象。

TLDR:如何在不改变类\函数代码的情况下改变函数\类使用接口的方式?

如果您能指出我的想法中的错误,我也很高兴。

示例: 假设我需要为某些不允许修改的类 (MoneyAdder) 开发日志记录机制(实现 ILogger 接口)。我还需要通过适配器实现其他一些记录器的使用 (请给我一个正确的术语) ,以便我们选择最佳方式。

class MoneyAdder
{
    private ILogger logger;
    private Customer customer;
    public MoneyAdder(ILogger logger, Customer customer)
    {
        this.logger = logger;
    }
    public void AddMoney(int amount)
    {
        logger.log("Doing work!");
        customer.balance+=amount;
        logger.log("I'm done!");
    }
}
  1. 这是我一开始做的:
public interface ILogger
{
    void log(string str);
}

public class MyLogger : ILogger
{
    public void log(string str)
    {
        Console.WriteLine($"LOG - {str}");
    }
}

在这种情况下,我可以完全控制接口定义、实现它的类,并且能够使用我想要的任何方式给出的日志字符串。

  1. 我们知道OtherLogger需要一个字符串和它的长度来写一个日志。为了使用它,我写了一个这样的适配器:
public class OtherLogger
{
    //We know it needs a string and its length for some reason.
    public void log2(string str, int i);
}

public class OtherLoggerAdapter : ILogger
{
    private OtherLogger ol = new OtherLogger();
    public void log(string str)
    {
        ol.log2(str, str.Length);
    }
}

通过这种方式,我将其他 dll调整到我的界面。当调用适配器时,我依次调用不同的方法名称。我还能够提供它需要的int,因为它可以从输入中计算出来。

  1. 现在我需要添加另一个需要日志字符串和引用它的程序集的记录器。我也可以提供。它不能从日志字符串中计算出来,但我可以给它任何通用信息,比如环境变量或程序名称,因为它对于程序、MoneyAdder 类和 StrangeLoggerAdapter是通用的。
public class StrangeLogger
{
    public void logS(string str, System.Reflection.Assembly assembly);
}

public class StrangeLoggerAdapter : ILogger
{
    private StrangeLogger sl = new StrangeLogger();

    public void log(string str)
    {
        sl.logS(str, System.Reflection.Assembly.GetExecutingAssembly());
    }
}
  1. 最终记录器是以前使用过的旧机制。它在 MoneyAdder 的其他方法中被直接引用和调用。(紧耦合,这是正确的术语吗?)。日志记录方法定义如下:
public class OldLogger
{
    public void log(string str, string customerName);
}

它需要一个客户名称,但它既不能从日志字符串中计算出来,也不能从我可以编写的任何适配器访问。使用它的唯一方法是将客户名称“注入”到这样的记录器中:

public interface ILogger
{
    void log(string str);
    void injectCustomer(string customerName);
}

然后在这样的适配器中实现它:

public class OldLoggerAdapter
{
    private string customerName;
    private OldLogger ol = new OldLogger();
    public void injectCustomer(string customerName)
    {
        this.customerName = customerName;
    }

    public void log(string str)
    {
        ol.log(str, this.customerName);
    }
}

但是,要使用该实现,我仍然需要修改(我不允许这样做)MoneyAdder 类或 AddMoney 方法以使用注入功能。

class MoneyAdder
{
    private ILogger logger;
    private Customer customer;
    public MoneyAdder(ILogger logger, Customer customer)
    {
        this.logger = logger;
        this.logger.injectCustomer(customer.Name);
    }
    public void AddMoney(int amount)
    {
        logger.log("Doing work!");
        customer.balance+=amount;
        logger.log("I'm done!");
    }
}

问题: 要实现日志记录功能,我只能使用信息,这些信息要么通过方法提供给函数,要么可以从该信息中计算出来,或者对整个程序都是全局的。

在不修改调用函数的情况下,无法直接提供或注入信息。

或者有吗?

有没有办法,使用一些 System\Reflexion\DI\IOC 魔法,写出类似的东西:

嘿,MoneyAdder,这是一个OldLogger,目前用作ILogger。每当您调用 log(string str) 时,您实际上应该调用我的方法 log(string str, string customerName)。我确定你有一个私有财产 Customer,它有一个 Customer.Name,在我的日志方法中使用它作为 "customerName"

标签: c#dependency-injectioninterfaceadapter

解决方案


推荐阅读