Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 同一接口的两个不同类的日志记录_C# - Fatal编程技术网

C# 同一接口的两个不同类的日志记录

C# 同一接口的两个不同类的日志记录,c#,C#,我正在尝试为两个相同接口类型的类创建一个decorator日志类,这将占用该类并基本上覆盖其方法步骤,以便它可以打印一些额外的内容。我发现这个解决方案非常糟糕,因为我正在重新实现已经实现的东西,但我想不出更好的解决方案 public class A :IA { private int state = 0; public void printStep() { Console.WriteLine("A state: {0}", state); }

我正在尝试为两个相同接口类型的类创建一个decorator日志类,这将占用该类并基本上覆盖其方法步骤,以便它可以打印一些额外的内容。我发现这个解决方案非常糟糕,因为我正在重新实现已经实现的东西,但我想不出更好的解决方案

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步骤()
{
重新