首先对问题/标题表示歉意。我找不到合适的标题。任何建议都非常欢迎。
我有一个C#应用程序,其逻辑类似于以下内容:
public ClassA {
public string myID { get; set; }
public void SetID(string jobID)
{
myID = jobID;
}
public void SomeMethod(){
ClassB b = new ClassB();
LogMessage("Execution starts here");
b.FetchData();
LogMessage("Further execution");
}
public void LogMessage (string message){
//some logic to write message into a text file with the following message :
// "Id : " + myID + " --> " + message
// next line (enter)
}
}
public class ClassB(){
public void FetchData(){
ClassA a = new ClassA();
a.LogMessage("Fetch data starts");
//some logic to fetch data
a.LogMessage("Fetch data ends");
}
}
如果id值说为“ ABC”,则执行后的文本文件如下所示:
Id : ABC --> Execution starts here
Id : (null) --> Fetch data starts
Id : (null) --> Fetch data ends
Id : ABC --> Further execution
我面临的问题是即使id是一个公共变量,id也不会被打印。当执行进入另一个类时,myId
变量变为null。出于某些原因,我也无法传递{{ 1}}变量作为myId
的参数。
谁能告诉我总是简单的方法来获取myId值,而不会在所有方法中都将其设置为null。上面的代码只是我在应用程序中拥有的示例,这种相似的日志记录在很多方法中都可以完成。因此,如果有人可以提出可以在LogMessage()
中进行更改的建议,那么这对我会有很大帮助。
请让我知道是否需要任何进一步的说明来理解该问题。
答案 0 :(得分:2)
LE:我看到您纠正了变量错字,现在我看到了问题。
在ClassB内部,您再次实例化包含LogMessage的ClassA,但是您没有调用SetID(因此myID为null)。
LE2:在这些类的任何一个中,我都不会使用log方法,因为SOLID原则中的S声明(一个类需要承担单个责任)。您可以采用的一种方法是创建一个处理日志逻辑的静态类:
public static class Logger
{
private static string myID;
public static SetMyId(string id)
{
myID = id;
}
public static void Log(string message)
{
//print myID _+ message
}
}
只要应用程序处于活动状态,静态变量就会保留您的ID。当然,确实有一些模式可用于此目的,因此根据您的上下文,根据您的需求(我在一个简单的Google搜索中发现的example)探索其他不同的选项以及执行该操作的库可能会很不错。为您记录日志(某些示例here)
答案 1 :(得分:1)
每个类实例都存在类变量,也称为字段(在这里我不是在谈论静态字段)。也就是说,每个对象都有自己的一组字段值。
在ClassB
中,用ClassA a = new ClassA();
创建一个新对象。这与您呼叫SomeMethod
的对象不同。
您可以通过构造函数注入将ClassA
对象传递给ClassB
。将ClassB
更改为
public class ClassB()
{
private readonly ClassA _a;
// Constructor. You call it with `new ClassB(classAObject)`.
public ClassB(ClassA a)
{
_a = a;
}
public void FetchData(){
_a.LogMessage("Fetch data starts");
// Fetching data here...
_a.LogMessage("Fetch data ends");
}
}
在ClassA
中将SomeMethod
更改为
public void SomeMethod()
{
myID = "ABC";
// Pass a reference to the current object (this).
ClassB b = new ClassB(this);
LogMessage("Execution starts here");
b.FetchData();
LogMessage("Further execution");
}
此外,由于SetID
属性已经具有公共设置器,因此没有必要创建方法myID
。
答案 2 :(得分:0)
您需要在日志消息中添加字符串,因为您要传递一个名为message的变量,该变量应该是字符串?
class QPushButton(QAbstractButton):
"""
QPushButton(parent: QWidget = None)
QPushButton(str, parent: QWidget = None)
QPushButton(QIcon, str, parent: QWidget = None)
"""
def actionEvent(self, *args, **kwargs): # real signature unknown
pass
def autoDefault(self): # real signature unknown; restored from __doc__
""" autoDefault(self) -> bool """
return False
def changeEvent(self, *args, **kwargs): # real signature unknown
pass
在B类中,没有指向您创建的A类实例的引用指针。因此,我不确定您如何调用该方法。
添加
public void LogMessage (string message){
//some logic to write message into a text file with the following message :
// "Id : " + myID + " --> " + message
// next line (enter)
}
答案 3 :(得分:0)
只需简单介绍一下如何解耦:“快速且非常脏”:
public class Logger {
public void LogMessage (string message, string myID){
//some logic to write message into a text file with the following message :
// "Id : " + myID + " --> " + message
// next line (enter)
}
}
public ClassA {
private Logger logger = new Logger();
public string myID { get; set; }
// SetID is actually not necessary: just use classAInstance.myID = jobID; in the client of ClassA.
// But I'd recommend making the Property Readonly and set it through CTOR if possible.
public void SomeMethod(){
ClassB b = new ClassB();
logger.LogMessage("Execution starts here", myID);
b.FetchData(logger, myID);
logger.LogMessage("Further execution", myID);
}
}
public class ClassB(){
public void FetchData( Logger logger, string myID){
logger.LogMessage("Fetch data starts", myID);
//some logic to fetch data
logger.LogMessage("Fetch data ends", myID);
}
}
可以通过以下方法进一步改进: