我正在尝试通过.NET 4.5中包含的Event Tracing for Windows (ETW)类在我的.NET应用程序中使用EventSource。我将EventSource
子类化为MyEventSource
并尝试实现接口IMyEventSource
(用于模拟目的),如下所示:
public interface IMyEventSource
{
void Test();
}
public class MyEventSource : EventSource, IMyEventSource
{
public static MyEventSource Log = new MyEventSource();
[Event(1)]
public void Test()
{
this.WriteEvent(1);
}
}
当我运行PerfView并执行此代码时,我会在调用IndexOutOfRangeException
时收到WriteEvent
。如果我通过修改代码删除界面......
public class MyEventSource : EventSource
{
public static MyEventSource Log = new MyEventSource();
[Event(1)]
public void Test()
{
this.WriteEvent(1);
}
}
...然后一切正常。
以下是我在两种情况下用于测试的代码:
static void Main(string[] args)
{
MyEventSource.Log.Test();
}
为什么我的EventSource
的子类如果只是实现一个接口就会中断?
这是related post。
答案 0 :(得分:12)
在提问时,@ LarsSkovslund的回答是正确的。但是,对于Microsoft.Diagnostics.Tracing.EventSource的稳定版本,Microsoft changed this according to their blog post:
通过RTM版本,我们放宽了一些事件源验证 规则以启用某些高级使用方案。
这方面的两个变化:
EventSource类型现在可以实现接口,以便在使用接口的高级日志记录系统中使用事件源类型 定义一个共同的记录目标。
引入了实用程序事件源类型的概念(定义为派生自EventSource的抽象类)以支持共享代码 跨项目中的多个事件源类型(例如,用于优化 WriteEvent()重载)。
系统。随.NET Framework提供的.Diagnostics.Tracing.EventSource支持.NET 4.6以上的这些方案
答案 1 :(得分:5)
虽然你不能让事件源实现一个接口,但是可以用另一个类包装它。 (这是Adapter design pattern)
的一个实例public class EventSourceAdapter : IEventSource
{
private MyEventSource log;
public EventSourceAdapter(MyEventSource log)
{
this.log = log;
}
public void Test()
{
log.Test()
}
}
}
答案 2 :(得分:4)
当EventSource类基于反射构建其事件结构时,它将仅考虑直接方法,例如在您的情况下,使用IMyEventSource不会考虑继承的成员。
您正在获取IndexOutOfRangeException,因为WriteEvent将使用event id参数来查找索引与事件id匹配的描述符块,从而在index不存在时抛出异常。
因此,简而言之,DONT使用接口来使用EventSource定义您的ETW事件。
干杯 拉斯
答案 3 :(得分:1)
截至今天(2014年9月29日),原始海报提供的代码不适用于.NET 4.5附带的本机代码。它仍然会生成一个" IndexOutOfRange"例外,正如他所说,只有在监控ETW事件时才会这样做(我使用的是PerfView)。
也就是说,我使用来自nuget.org的Microsoft EventSource库检查.NET 4.0版,他的代码确实可以使用。
我接下来在.NET 4.5版项目中从nuget安装了Microsoft EventSource Library。我确保从Microsoft.Diagnostics.Tracing.EventSource继承而不是从本机.NET 4.5库中的System.Diagnostics.Tracing.EventSource继承。这很有用,但我还发现我必须使用[Microsoft.Diagnostics.Tracing.Event(int)]属性标记从接口继承的那些方法。
我也观察到一些我无法解释的奇怪行为。有时我的一些事件在PerfView中显示为名为" EventID(0)"而不是方法名称。有时我得到意外的IndexOutOfRange异常。我可以猜测,之前的试验中的注册仍然在记忆中。我开始在试验之间重命名我的EventSource类,我不再遇到这些问题了。
JR
答案 4 :(得分:0)
这个问题有一个解决方法(抱歉,我不知道如何解释这个问题)。
如果你的方法是用NonEventAttribute
装饰的,你将可以使用你的界面。
您的界面:
public interface IMyEventSource
{
void Test();
}
实施:
public class MyEventSource : EventSource, IMyEventSource
{
public static MyEventSource Log = new MyEventSource();
[NonEvent]
public void Test()
{
this.InternalTest();
}
[Event(1)]
private void InternalTest()
{
this.WriteEvent(1);
}
}