【发布时间】:2018-12-21 14:35:08
【问题描述】:
我有一组继承自 ConfigurationSection 类的类。我还有一个Logger 类,用于为每个类创建单独的日志文件,但这还不包括这些配置类。
我不想为每个ConfigurationSection 类创建一个新的Logger 实例(因此,一个新的日志文件),我希望它们都使用同一个实例,并登录到同一个文件。
实现这一目标的最佳方法是什么?
以下是我考虑过的几个选项。
在实例化每个相关类时将实例化的 Logger 作为参数传递
这似乎是最明显的选择,但我真的不喜欢它。我的Logger 类并不完全是轻量级的,我宁愿避免传递如此大的参数。无论如何,这是一种选择。
class Program
{
static void Main( string[] args )
{
// These variables are used for illustrative purposed,
// instead of showing my `Logger' class
bool loggerInstantiated = true;
DateTime InstantiatedTime = DateTime.Now;
DerivedClass01 dc01 = new DerivedClass01( loggerInstantiated, InstantiatedTime );
// added to create delay between the instantiation of different derived classes
System.Threading.Thread.Sleep( 1000 );
DerivedClass02 dc02 = new DerivedClass02( loggerInstantiated, InstantiatedTime );
}
}
class BaseClass : ConfigurationSection
{
public BaseClass( bool loggerInstantiated, DateTime instantiatedAt )
{
Console.WriteLine(string.Format("BaseClass:\n\r\tLoggerInitiated is {0} at {1}\n\r", loggerInstantiated, instantiatedAt ) );
}
}
class DerivedClass01 : BaseClass
{
public DerivedClass01( bool loggerInstantiated, DateTime instantiatedAt ) : base(loggerInstantiated, instantiatedAt)
{
Console.WriteLine( string.Format( "DerivedClass01:\n\r\tLoggerInitiated is {0} at {1}\n\r", loggerInstantiated, instantiatedAt ) );
}
}
class DerivedClass02 : BaseClass
{
public DerivedClass02( bool loggerInstantiated, DateTime instantiatedAt ) : base( loggerInstantiated, instantiatedAt )
{
Console.WriteLine( string.Format( "DerivedClass02:\n\r\tLoggerInitiated is {0} at {1}\n\r", loggerInstantiated, instantiatedAt ) );
}
}
输出:
/*
BaseClass:
LoggerInitiated is True at 21/12/2018 14:16:09
DerivedClass01:
LoggerInitiated is True at 21/12/2018 14:16:09
BaseClass:
LoggerInitiated is True at 21/12/2018 14:16:09
DerivedClass02:
LoggerInitiated is True at 21/12/2018 14:16:09
*/
结论:
这当然是一种选择。从BaseClass 派生的每个类都可以使用相同的Logger。但是由于我的Logger 类的大小,我认为最好不要将整个实例作为参数传递。
编辑:
正如@Malior 和@ScottHannen 所指出的,当您将类的实例作为参数时,我完全误解了实际发生的情况。我不想这样做的原因现在有些无效,但我仍然宁愿在实例化派生自BaseClass 的类时不必将Logger 作为参数传递。
从基类继承
创建一个继承自ConfigurationSection 的BaseClass,并在BaseClass 上实例化Logger。任何相关的ConfigurationSection 类都可以从这个BaseClass 继承。
代码:
class Program
{
static void Main( string[] args )
{
DerivedClass01 dc01 = new DerivedClass01();
// added to create delay between the instantiation of different derived classes
System.Threading.Thread.Sleep( 1000 );
DerivedClass02 dc02 = new DerivedClass02();
}
}
class BaseClass : ConfigurationSection
{
// These variables are used for illustrative purposed,
// instead of showing my `Logger' class
public bool LoggerInstantiated;
public DateTime InstantiatedAt;
public BaseClass()
{
LoggerInstantiated = true;
InstantiatedAt = DateTime.Now;
Console.WriteLine(string.Format("BaseClass:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt));
}
}
class DerivedClass01 : BaseClass
{
public DerivedClass01()
{
Console.WriteLine( string.Format( "DerivedClass01:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt ) );
}
}
class DerivedClass02 : BaseClass
{
public DerivedClass02()
{
Console.WriteLine( string.Format( "DerivedClass02:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt ) );
}
}
输出:
/*
BaseClass:
LoggerInitiated is True at 21/12/2018 14:21:51
DerivedClass01:
LoggerInitiated is True at 21/12/2018 14:21:51
BaseClass:
LoggerInitiated is True at 21/12/2018 14:21:52
DerivedClass02:
LoggerInitiated is True at 21/12/2018 14:21:52
*/
结论:
这不好。每次实例化派生类时都会创建一个新实例 Logger(这很明显 - 我应该早点意识到......)
从包含静态 Logger 的基类继承
与上面类似,但不是实例Logger,而是有一个静态实例。在实例化DerivedClasses 之前创建它,并且不要在BaseClass 构造函数中创建新实例。
代码:
class Program
{
static void Main( string[] args )
{
BaseClass.LoggerInstantiated = true;
BaseClass.InstantiatedAt = DateTime.Now;
DerivedClass01 dc01 = new DerivedClass01();
// added to create delay between the instantiation of different derived classes
System.Threading.Thread.Sleep( 1000 );
DerivedClass02 dc02 = new DerivedClass02();
}
}
class BaseClass : ConfigurationSection
{
// These variables are used for illustrative purposed,
// instead of showing my `Logger' class
public static bool LoggerInstantiated;
public static DateTime InstantiatedAt;
public BaseClass()
{
Console.WriteLine(string.Format("BaseClass:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt));
}
}
class DerivedClass01 : BaseClass
{
public DerivedClass01()
{
Console.WriteLine( string.Format( "DerivedClass01:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt ) );
}
}
class DerivedClass02 : BaseClass
{
public DerivedClass02()
{
Console.WriteLine( string.Format( "DerivedClass02:\n\r\tLoggerInitiated is {0} at {1}\n\r", LoggerInstantiated, InstantiatedAt ) );
}
}
输出:
/*
BaseClass:
LoggerInitiated is True at 21/12/2018 14:05:56
DerivedClass01:
LoggerInitiated is True at 21/12/2018 14:05:56
BaseClass:
LoggerInitiated is True at 21/12/2018 14:05:56
DerivedClass02:
LoggerInitiated is True at 21/12/2018 14:05:56
*/
结论:
这似乎是一个合理的选择。从BaseClass 派生的每个类都可以访问相同的Logger,而无需将其作为参数传递。
【问题讨论】:
-
为什么不把记录器做成一个静态类,不用实例化就到处使用呢?
-
@NikhilVartak 问题是相关部分,只有几行。其余的只是我尝试过的各种选择。随意忽略它们,并根据我的问题为我提供一些帮助。谢谢
-
@rashmatash 实际上这不是一个坏主意,但这意味着对许多现有代码进行相当大的更改。我认为我更喜欢我的第三个选项(上图),即在
BaseClass中对实例化记录器进行静态引用,因为精简意味着对现有代码的更改更少。谢谢 -
在您的第一个示例中,记录器类的大小是什么意思?它是一个类实例,你只转发指针。这不重。
-
您能否澄清一下:“但由于我的 Logger 类的大小,我认为最好不要将整个实例作为参数传递。” “大小”是什么意思?当您传递对对象的引用时,您只是传递了一个指针。它没有创造任何新的东西或复制任何现有的东西。所以你可能会担心一些无关紧要的事情。
标签: c# class inheritance