问题描述
目前我具备的功能CreateLog()创建AA log4net的日志与施工实例的课后名。通常用作:
类的messageReceiver
{
受保护的ILog日志= Util.CreateLog();
...
}
如果我们去掉大量的错误处理的实施归结为:
公开的ILog CreateLog()
{
System.Diagnostics.StackFrame的StackFrame =新System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase方法= stackFrame.GetMethod();
返回CreateLogWithName(method.DeclaringType.FullName);
}
问题是,如果我们inheirit的messageReceiver为子类中的日志仍然需要它的名字从的messageReceiver,因为这是声明类的方法(构造函数),它调用CreateLog。
类IMReceiver:的messageReceiver
{...}
类EmailReceiver:的messageReceiver
{...}
这两个类的实例会得到日志名称为的messageReceiver,而我想他们是赐名IMReceiver和EmailReceiver。
我知道这很容易做到(并完成)通过以来对象的GetType()方法调用CreateLog时传递一个参考对象在创造我想要做什么。
有一些小的原因preFER不添加参数,我个人觉得被没有找到,没有额外的参数的解决方案感到不安。
是否有将被命名为从子类,谁可以告诉我如何实现一个无参数的CreateLog()不是声明类?
编辑:
在CreateLog功能不超过上面提到的。这样做的原因具有每个实例一个日志的是能够在日志文件中的不同实例之间不同。这是由CreateLog / CreateLogWithName对实施
扩展在CreateLog()的功能来激励它的存在。
公开的ILog CreateLog()
{
System.Diagnostics.StackFrame的StackFrame =新System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase方法= stackFrame.GetMethod();
类型Type = method.DeclaringType;
如果(method.IsStatic)
{
返回CreateLogWithName(type.FullName);
}
其他
{
返回CreateLogWithName(type.FullName + - + GetAndInstanceCountFor(类型));
}
}
此外,我preFER写的ILog登录= Util.CreateLog();而不是每当我写一个新的类的其他文件中的一些长期神秘的行复制。我知道,在Util.CreateLog使用的反射不能保证工作,虽然 - ?是System.Reflection.MethodBase.GetCurrentMethod()保证正常工作
我不认为你将能够通过查看堆栈帧来做到这一点。
当你的类 IMReceiver
,调用 CreateLog
方法是在的messageReceiver
类。堆栈帧必须告诉你那里的方法是从所谓的,否则也不会有任何使用,所以它总是会说的messageReceiver
如果你叫 CreateLog
明确你的 IMReceiver
及其他类,那么它的工作原理,如堆栈帧显示被称为在派生类中的方法(因为它实际上是)。
下面是我能想出的最好的事情:
类的BaseClass {
公共日志记录= Utils.CreateLog();
}
类DerivedClass:BaseClass的{
公共DerivedClass(){
登录= Utils.CreateLog();
}
}
如果我们追溯创建日志,我们得到这样的:
新的BaseClass();
对BaseClass的#日志创建
新DerivedClass();
对BaseClass的#日志创建
#日志以DerivedClass创建
第二个日志中的派生类中创建覆盖实例变量,所以你的code会正常运行,你只是要创建并立即被扔掉一个BaseClass的日志。这似乎哈克和对我不好,我只是去指定构造函数的类型参数或使用一个通用的。
恕我直言指定类型比堆栈帧闲逛反正清洁
如果你能得到它不看堆栈帧,你的选择大大扩展
Currently I have the function CreateLog() for creating a a log4net Log with name after the constructing instance's class. Typically used as in:
class MessageReceiver
{
protected ILog Log = Util.CreateLog();
...
}
If we remove lots of error handling the implementation boils down to:[EDIT: Please read the longer version of CreateLog further on in this post.]
public ILog CreateLog()
{
System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase method = stackFrame.GetMethod();
return CreateLogWithName(method.DeclaringType.FullName);
}
Problem is that if we inheirit MessageReceiver into sub classes the log will still take its name from MessageReceiver since this is the declaring class of the method (constructor) which calls CreateLog.
class IMReceiver : MessageReceiver
{ ... }
class EmailReceiver : MessageReceiver
{ ... }
Instances of both these classes would get Logs with name "MessageReceiver" while I would like them to be given names "IMReceiver" and "EmailReceiver".
I know this can easily be done (and is done) by passing a reference to the object in creation when calling CreateLog since the GetType() method on object does what I want.
There are some minor reasons to prefer not adding the parameter and personally I feel disturbed by not finding a solution with no extra argument.
Is there anyone who can show me how to implement a zero argument CreateLog() that gets the name from the subclass and not the declaring class?
EDIT:
The CreateLog function does more than mentioned above. The reason for having one log per instance is to be able to differ between different instances in the logfile. This is enforced by the CreateLog/CreateLogWithName pair.
Expanding on the functionality of CreateLog() to motivate its existence.
public ILog CreateLog()
{
System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase method = stackFrame.GetMethod();
Type type = method.DeclaringType;
if (method.IsStatic)
{
return CreateLogWithName(type.FullName);
}
else
{
return CreateLogWithName(type.FullName + "-" + GetAndInstanceCountFor(type));
}
}
Also I prefer writing ILog Log = Util.CreateLog(); rather than copying in some long cryptic line from an other file whenever I write a new class. I am aware that the reflection used in Util.CreateLog is not guaranteed to work though - is System.Reflection.MethodBase.GetCurrentMethod() guaranteed to work?
I don't think you'll be able to do it by looking at the stack frame.
While your class is IMReceiver
, the call to CreateLog
method is in the MessageReceiver
class. The stack frame must tell you where the method is being called from, or it wouldn't be any use, so it's always going to say MessageReceiver
If you called CreateLog
explicitly in your IMReceiver
and other classes, then it works, as the stack frame shows the method being called in the derived class (because it actually is).
Here's the best thing I can come up with:
class BaseClass{
public Log log = Utils.CreateLog();
}
class DerivedClass : BaseClass {
public DerivedClass() {
log = Utils.CreateLog();
}
}
If we trace creation of logs, we get this:
new BaseClass();
# Log created for BaseClass
new DerivedClass();
# Log created for BaseClass
# Log created for DerivedClass
The second 'log created for derived class' overwrites the instance variable, so your code will behave correctly, you'll just be creating a BaseClass log which immediately gets thrown away. This seems hacky and bad to me, I'd just go with specifying the type parameter in the constructor or using a generic.
IMHO specifying the type is cleaner than poking around in the stack frame anyway
If you can get it without looking at the stack frame, your options expand considerably
这篇关于我如何找到当前函数的调用函数的对象实例的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!