c# - 有没有办法实现适配器或接口而不更改在这种情况下使用它的类?
问题描述
我正在尝试学习和理解接口、适配器和依赖注入以及如何使用它们来实现抽象。
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!");
}
}
- 这是我一开始做的:
public interface ILogger
{
void log(string str);
}
public class MyLogger : ILogger
{
public void log(string str)
{
Console.WriteLine($"LOG - {str}");
}
}
在这种情况下,我可以完全控制接口定义、实现它的类,并且能够使用我想要的任何方式给出的日志字符串。
- 我们知道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,因为它可以从输入中计算出来。
- 现在我需要添加另一个需要日志字符串和引用它的程序集的记录器。我也可以提供。它不能从日志字符串中计算出来,但我可以给它任何通用信息,比如环境变量或程序名称,因为它对于程序、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());
}
}
- 最终记录器是以前使用过的旧机制。它在 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"。
解决方案
推荐阅读
- r - 如何在 R 中选择具有条件的列的一部分?
- kubernetes - 如何在“kubectrl run”中使用 kubernetes secret
- python-3.8 - Python3:FileNotFoundError:[Errno 2] 没有这样的文件或目录:'FIRST_FILENAME.pdf'
- android - 图片未显示在 RecyclerView 中
- c# - 如何使用 C# 在 Selenium 中使元素显示为真
- spring-integration - 使用 spring 集成向非 jms 客户端发送消息
- python - 大熊猫的时间换算
- jquery - JQuery 使用 ------WebKitFormBoundary 而不是序列化变量发送 POST 表单数据
- erlang - 如何美化 Erlang 术语以使其可读?
- java - 从 Web Api 服务获取数据时,为什么屏幕旋转上的 savedInstanceState 不起作用?