C# 仅当DLL可用时才使用库

C# 仅当DLL可用时才使用库,c#,dll,proxy,nlog,C#,Dll,Proxy,Nlog,我正在我的一些库中使用NLog,我希望我的库能够正常工作,即使我的用户没有NLog dll 到目前为止,我的解决方案是为我正在使用的类创建一个ILogger接口,并在找到NLog dll时使用反射从NLog调用方法 问题是,这种方法有时非常慢,在我的情况下会导致CPU使用率增加约10%(有些地方我会做大量日志记录) 我的问题有没有更通用的解决方案?也许使用emit这样我就不会有这样的性能冲击?似乎这个问题应该有一个简单的解决方案。我认为你的解决方案是唯一可能的,那就是使用反射。 事实上,反射在计

我正在我的一些库中使用NLog,我希望我的库能够正常工作,即使我的用户没有NLog dll

到目前为止,我的解决方案是为我正在使用的类创建一个ILogger接口,并在找到NLog dll时使用反射从NLog调用方法

问题是,这种方法有时非常慢,在我的情况下会导致CPU使用率增加约10%(有些地方我会做大量日志记录)


我的问题有没有更通用的解决方案?也许使用emit这样我就不会有这样的性能冲击?似乎这个问题应该有一个简单的解决方案。

我认为你的解决方案是唯一可能的,那就是使用反射。
事实上,反射在计算方面更昂贵。

我的解决方案与(如发布的)类似

我的解决方案的反射部分导致了slowup,因此我最终使用linq表达式创建了所有记录器方法的编译版本。通过这种方式,我在启动时的执行时间略有增加,但在整个程序期间(有时以天为单位)的执行时间更快

新版本(更快):

这比旧版本要复杂得多,在旧版本中,我只是将记录器声明为动态的

dynamic logger = ....
// ...
logger.IsTraceEnabled;
logger.Trace("message");
但在我的特殊情况下,加速是显而易见的。现在我只有大约1%的slowup。我做了更多的测量,结果表明,其背后的实际原因是检查跟踪是否启用的调用次数过多。在发布版本中,跟踪被关闭,但我仍然有大约14个记录器,他们的IsTraceAbled属性我必须不断地探测


事后看来,我本可以缓存iEnabled属性的值并获得类似的启动,但哦,好吧。。。我注意到有点晚了。

只检查一次并缓存检查结果,而不是每次都检查。@SynerCoder:我已经这样做了,我的检查的过期时间是500毫秒,但在我看来,我的瓶颈是调用调用。如果稍微自定义库没有问题,您可以尝试一下为什么过期时间?在我看来,如果库在那里,它就会留在那里。@SynerCoder:我这样做是因为执行时间长,而且是因为部署的方式(它是一个可以将插件推送到正在运行的程序中的系统)。但是你是对的,我仍然可以缓存至少iEnabled的值,并且我可以恢复性能。我认为emit解决方案也是可能的,类似于:Invoke用于创建对象,emit用于调用代理方法。问题是我不适合il emit magic,我希望有一个解决方案可以为我生成代码。
Action<object, string> trace = CreateMethod<string>(logger.GetType(), "Trace");
Func<object, bool> isTraceEnabled = CreateGetter<bool>(logger.GetType(), "IsTraceEnabled");
isTraceEnabled(logger);
trace(logger, "message")
dynamic logger = ....
// ...
logger.IsTraceEnabled;
logger.Trace("message");