C# 同一接口的两个不同类的日志记录
我正在尝试为两个相同接口类型的类创建一个decorator日志类,这将占用该类并基本上覆盖其方法步骤,以便它可以打印一些额外的内容。我发现这个解决方案非常糟糕,因为我正在重新实现已经实现的东西,但我想不出更好的解决方案C# 同一接口的两个不同类的日志记录,c#,C#,我正在尝试为两个相同接口类型的类创建一个decorator日志类,这将占用该类并基本上覆盖其方法步骤,以便它可以打印一些额外的内容。我发现这个解决方案非常糟糕,因为我正在重新实现已经实现的东西,但我想不出更好的解决方案 public class A :IA { private int state = 0; public void printStep() { Console.WriteLine("A state: {0}", state); }
public class A :IA
{
private int state = 0;
public void printStep()
{
Console.WriteLine("A state: {0}", state);
}
public bool Step()
{
state++;
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : IA
{
private double state = 0.0;
public void printStep()
{
Console.WriteLine("B state: {0}", state);
}
public bool Step()
{
state+= 0.1;
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
public void Run() //Don't like this method especially because it shouldn't reimplement the run methods again
{
if (ia.GetType() == typeof(A))
{
for (int i = 0; i < 5; ++i)
{
ia.printStep();
ia.Step();
}
}
else
{
for (int i = 0; i < 4; ++i)
{
ia.printStep();
ia.Step();
}
}
}
}
编辑2:我需要调用原始的Run方法,该方法将使用添加的日志调用更新的Step方法。这个简单示例的预期行为是A类记录器将打印符号A 5次,B类记录器将打印符号B 4次
编辑3:我为什么要做这种行为?我觉得有两个类A和B可以完全工作,而不需要自己编写任何信息。记录器应记录其中任何一个,并记录每个步骤后通常会改变的每个状态。所以我会得到一个完美的信息。我可以在a和B类中添加一个布尔变量,但感觉不太对劲
public class A :IA
{
...
public bool Step()
{
if (logging) printStep();
state++;
return true;
}
...
编辑5:更改初始代码,使其更有意义。
使用:
预期产出:
A state: 5
A state: 6
A state: 7
A state: 8
A state: 9
B state: 0.4
B state: 0.5
B state: 0.6
B state: 0.7
如果希望Logger类实现Decorator模式,它必须实现与“修饰”类相同的接口(而不仅仅是像在代码段中那样封装它们) 通过这样做,您将能够实现所需的行为(类似于编辑中的行为) 编辑: 假设日志记录器负责记录某些内容,IA不必包含printStep()方法 因此,我们:
public interface IA
{
bool Step();
}
public class A : IA
{
public bool Step()
{
return true;
}
}
public class B : IA
{
public bool Step()
{
return true;
}
}
public class Logger : IA
{
private readonly IA _decorated;
public Logger(IA decorated)
{
_decorated = decorated;
}
public bool Step()
{
Console.WriteLine("Before Step...");
_decorated.Step();
Console.WriteLine("Step completed.");
}
}
实例化记录器时,需要传递要修饰的对象
IA notDecorated = new A();
IA decorated = new Logger(notDecorated);
如果希望Logger类实现Decorator模式,它必须实现与“修饰”类相同的接口(而不仅仅是像在代码段中那样封装它们) 通过这样做,您将能够实现所需的行为(类似于编辑中的行为) 编辑: 假设日志记录器负责记录某些内容,IA不必包含printStep()方法 因此,我们:
public interface IA
{
bool Step();
}
public class A : IA
{
public bool Step()
{
return true;
}
}
public class B : IA
{
public bool Step()
{
return true;
}
}
public class Logger : IA
{
private readonly IA _decorated;
public Logger(IA decorated)
{
_decorated = decorated;
}
public bool Step()
{
Console.WriteLine("Before Step...");
_decorated.Step();
Console.WriteLine("Step completed.");
}
}
实例化记录器时,需要传递要修饰的对象
IA notDecorated = new A();
IA decorated = new Logger(notDecorated);
如果没有理由让其他对象直接调用
Step()
,那么它不应该是接口的一部分。然而,由于我认为您正在创建的类在形状上可能非常相似,但在实现上可能非常不同,所以我不认为装饰这些类会得到您想要的。我认为在需要的地方添加日志记录更有意义
我提供了一个现代日志框架(like)为您所做的玩具示例。在我的示例中,您可以通过传入不同的日志实现来更改是否有日志记录。在真实的框架中,您可以配置不同级别的日志记录,以便完全关闭日志记录或只记录更重要的信息
public class A : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
// some logic
logger.Info("Something specific here.")
// more logic
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
logger.Info("A");
Step();
}
}
}
public class B : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
logger.Info("B");
Step();
}
}
}
public interface IA
{
void Run();
}
public interface ILog
{
void Info(string message);
}
public class ConsoleLogger : ILog
{
public void Info(string message)
{
Console.WriteLine(message);
}
}
public class NoopLogger : ILog
{
public void Info(string message)
{
}
}
如果没有理由让其他对象直接调用
Step()
,那么它不应该是接口的一部分。然而,由于我认为您正在创建的类在形状上可能非常相似,但在实现上可能非常不同,所以我不认为装饰这些类会得到您想要的。我认为在需要的地方添加日志记录更有意义
我提供了一个现代日志框架(like)为您所做的玩具示例。在我的示例中,您可以通过传入不同的日志实现来更改是否有日志记录。在真实的框架中,您可以配置不同级别的日志记录,以便完全关闭日志记录或只记录更重要的信息
public class A : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
// some logic
logger.Info("Something specific here.")
// more logic
return true;
}
public void Run()
{
for (int i = 0; i < 5; ++i)
{
logger.Info("A");
Step();
}
}
}
public class B : IA
{
private readonly ILog logger;
public B(ILog logger)
{
this.logger = logger;
}
private bool Step()
{
return true;
}
public void Run()
{
for (int i = 0; i < 4; ++i)
{
logger.Info("B");
Step();
}
}
}
public interface IA
{
void Run();
}
public interface ILog
{
void Info(string message);
}
public class ConsoleLogger : ILog
{
public void Info(string message)
{
Console.WriteLine(message);
}
}
public class NoopLogger : ILog
{
public void Info(string message)
{
}
}
如果您想摆脱A和B中的共享功能,可以创建一个抽象类。在这里实现共享功能,并将其余方法抽象化。如果您严格地想要使用decorator模式,您可以为抽象类创建一个接口
public class A : AbstractA
{
public override void printStep()
{
Console.WriteLine("A");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : AbstractA
{
public override void printStep()
{
Console.WriteLine("B");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public abstract class AbstractA : IA
{
public abstract void printStep();
public virtual bool Step()
{
return true;
}
public virtual void Run()
{
printStep();
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
void Run()
{
ia.Run();
}
}
公共类A:AbstractA
{
公共覆盖无效打印步骤()
{
控制台。写入线(“A”);
}
公共覆盖无效运行()
{
base.Run();
对于(int i=0;i<5;++i)
{
步骤();
}
}
}
公共B类:抽象A
{
公共覆盖无效打印步骤()
{
控制台。写入线(“B”);
}
公共覆盖无效运行()
{
base.Run();
对于(int i=0;i<4;++i)
{
步骤();
}
}
}
公共抽象类AbstractA:IA
{
公共摘要void printStep();
公共虚拟bool步骤()
{
返回true;
}
公共虚拟空运行()
{
printStep();
}
}
公共接口
{
void printStep();
bool步骤();
无效运行();
}
公共类记录器
{
私人保险公司;
公共记录器(IA)
{
这是ia=ia;
}
无效运行()
{
ia.Run();
}
}
如果您想摆脱A和B中的共享功能,可以创建一个抽象类。在这里实现共享功能,并将其余方法抽象化。如果您严格地想要使用decorator模式,您可以为抽象类创建一个接口
public class A : AbstractA
{
public override void printStep()
{
Console.WriteLine("A");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 5; ++i)
{
Step();
}
}
}
public class B : AbstractA
{
public override void printStep()
{
Console.WriteLine("B");
}
public override void Run()
{
base.Run();
for (int i = 0; i < 4; ++i)
{
Step();
}
}
}
public abstract class AbstractA : IA
{
public abstract void printStep();
public virtual bool Step()
{
return true;
}
public virtual void Run()
{
printStep();
}
}
public interface IA
{
void printStep();
bool Step();
void Run();
}
public class Logger
{
private IA ia;
public Logger(IA ia)
{
this.ia = ia;
}
void Run()
{
ia.Run();
}
}
公共类A:AbstractA
{
公共覆盖无效打印步骤()
{
控制台。写入线(“A”);
}
公共覆盖无效运行()
{
base.Run();
对于(int i=0;i<5;++i)
{
步骤();
}
}
}
公共B类:抽象A
{
公共覆盖无效打印步骤()
{
控制台。写入线(“B”);
}
公共覆盖无效运行()
{
base.Run();
对于(int i=0;i<4;++i)
{
步骤();
}
}
}
公共抽象类AbstractA:IA
{
公共摘要void printStep();
公共虚拟bool步骤()
{
重新