使用Enterprise Library Unity与其他IoC容器(Windsor,Spring.Net,Autofac ..)的优缺点是什么?
.net c# enterprise-library inversion-of-control unity-container
有人知道Microsoft.Practices.ServiceLocation从哪里来的吗?这是MS EnterpriseLibrary中使用的命名空间和dll.不可否认,这是一个非常简单的dll,只有少数几个类(使用反射器),但我找不到已发布的源代码.它不在Enterprise Library项目中,也不在Unity项目中.
那么有人知道这个的源代码是否已发布以及在哪里?还有为什么它不是Unity的一部分?它在其他地方使用吗?
Unity依赖注入容器似乎是一个众所周知的问题,其中SynchronizedLifetimeManager经常会导致Monitor.Exit方法抛出SynchronizationLockException,然后捕获并忽略它.这对我来说是一个问题,因为我喜欢使用Visual Studio进行调试以打破任何抛出的异常,所以每次我的应用程序启动时,我都会无缘无故地多次打破这个异常.
如何防止抛出此异常?
无论在Web上的其他地方提到此问题,建议通常都涉及更改调试器设置以忽略它.这类似于去看医生并且说:"医生,医生,当我举起它时,我的手臂疼,"被告知,"好吧,停止提高它." 我正在寻找一种解决方案,可以阻止异常被抛出.
SetValue方法中发生异常,因为它假设首先调用GetValue,并调用Monitor.Enter.但是,LifetimeStrategy和UnityDefaultBehaviorExtension类都会定期调用SetValue而不调用GetValue.
我宁愿不必更改源代码并维护我自己的Unity版本,所以我希望有一个解决方案,我可以在容器中添加一些扩展,策略或策略的组合,以确保,如果生命周期管理器是一个SynchronizedLifetimeManager,GetValue始终先调用.
我的服务装饰如下
<ExceptionShielding("MyExceptionPolicyName")>
Run Code Online (Sandbox Code Playgroud)
当抛出一个错误异常时,我的策略会收到错误并登录就好了.它接受handlingInstance Id并将其与错误一起记录以供参考.我注意到的是,故障中返回的Guid"错误ID:"与传递给处理instanceId的Guid不同.
我也尝试过装饰这样的操作
<FaultContract(GetType(ValidationFault))>
Run Code Online (Sandbox Code Playgroud)
但这会产生相同的结果.
我想要做的是如何捕获"错误ID:"传递回消费者,以便我可以将其与异常一起记录.*附加信息:异常策略处理程序是一个自定义的处理异常,并将其各种属性和数据记录到特定的异常日志数据库模式中.
有谁知道怎么做到这一点?
更新: 根据@Jay Patel的评论,我将此添加到我的配置中以启用跟踪
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\Temp\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Run Code Online (Sandbox Code Playgroud)
然后,我执行了一个请求,以获得由异常屏蔽屏蔽的故障响应.故障响应字符串的格式如下:"使用此服务时出错.请联系您的管理员以获取更多信息.错误ID:{GUID}"
然后我查看了跟踪日志,发现没有GUID或此字符串的证据.
以下是使用ExceptionShielding时关心查看示例的任何人的tracelog 的pastebin链接.
UPDATE2:
再次,根据@Jay Patel的评论,补充说明.我为maxMessageLog尝试了-1和max int值,以确保我在该日志中获得最大量的数据.
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="2147483647" />
</diagnostics>
Run Code Online (Sandbox Code Playgroud)
日志没有帮助.它甚至不包括任何关于回答我的问题的内容.
为了澄清以防上面不清楚...我希望能够在消息中的"错误ID:"之后捕获GUID回到客户端,这样我就可以使用异常处理程序记录的异常来记录它.这样,客户端可以联系"管理员",因为消息显示错误ID,并且实际上能够找到某些内容.
这是启用完整跟踪的pastbin
在visual studio中,我有一个使用MS Enterprise Library 4.0应用程序块的asp.net 3.5项目.
当我打开我的Web配置文件时,我的错误列表中填满了99条消息
Could not find schema information for the element 'dataConfiguration'.
Could not find schema information for the attribute 'defaultDatabase'.
Could not find schema information for the element 'loggingConfiguration'.
Could not find schema information for the attribute 'tracingEnabled'.
Could not find schema information for the attribute 'defaultCategory'.
Run Code Online (Sandbox Code Playgroud)
如果我关闭Web.config文件,它们就会消失(但是一旦我需要再次打开文件它们就会回来).
经过一番研究后,我发现这是因为缺少Visual Studio所需的XSD或模式文件,以便正确"理解"web.config文件中的模式并为其提供智能感知.
有谁知道如何为VS提供适当的架构信息,或者关闭这些消息?
@Franci - 感谢您的信息,我已经尝试过该工具以及MMC管理单元(它们往往会破坏Web.config中的格式),但它们仍然无法解决我收到的恼人警告.谢谢你的尝试.
如何在标准跟踪,Logger.NET,企业库,log4net或Ukadc.Diagnostics之间进行选择?
是否存在一个比另一个更合适的情况?那会是什么?(ASP.NET,控制台应用,Azure云,SOHO,企业...)
有什么好处或缺点?
我是否错过了其他主要的日志记录框架?
我在我的一个项目中使用Enterprise Library 4进行日志记录(以及其他用途).我注意到我正在做的日志记录有一些成本,我可以通过在单独的线程上进行日志记录来减轻这种成本.
我现在这样做的方法是创建一个LogEntry对象,然后在调用Logger.Write的委托上调用BeginInvoke.
new Action<LogEntry>(Logger.Write).BeginInvoke(le, null, null);
Run Code Online (Sandbox Code Playgroud)
我真正想做的是将日志消息添加到队列中,然后让一个线程将LogEntry实例从队列中拉出并执行日志操作.这样做的好处是日志记录不会干扰执行操作,并且并非每个日志记录操作都会导致在线程池上抛出作业.
如何以线程安全的方式创建支持多个编写器和一个读取器的共享队列?设计用于支持许多编写器(不会导致同步/阻塞)和单个读取器的队列实现的一些示例将非常受欢迎.
关于替代方法的建议也将受到赞赏,但我对改变日志框架并不感兴趣.
对于将在Web应用程序和富客户端应用程序中使用的.NET组件,似乎有两个明显的缓存选项:System.Web.Caching或Ent.库.缓存块.
在Web应用程序之外使用是否安全?我看到了混合信息,但我认为答案可能并非如此.
我不希望使用它的一个亮点,SqlCacheDependency,但在.NET 3.5中添加CacheItemUpdateCallback似乎是一件非常好的事情.
某些缓存项应始终可用,但应定期刷新.对于这些项目,在删除项目后获取回调不是很方便.看起来客户端必须只是睡眠和轮询,直到重新填充缓存项.
当您不需要分布式缓存时,有什么优缺点?
我已经比较了.NET 4.0中的system.runtime.caching和企业库缓存块的性能,令我惊讶的是,当从缓存项中获取大数据集时,它的表现非常糟糕.
Enterprise Library在大约0,15ms内获取100个对象,在大约0.25ms内获取10000个对象.这对于进程内缓存来说是快速且自然的,因为实际上不需要复制数据(仅引用).
.NET 4.0缓存在大约25毫秒内获取100个对象,在大约1500毫秒内获取10000个对象!相比之下这非常慢,这让我怀疑缓存是在进程外完成的.
我是否缺少一些配置选项,例如启用进程内缓存,还是企业库缓存块真的这么快?
更新
这是我的基准:
首先,我将数据从数据库加载到缓存(与基准分开).
我在get方法周围使用一个计时器来测量时间(以毫秒为单位):
EnterpriseLibrary缓存
Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager _cache;
public void InitCache(){
_cache = CacheFactory.GetCacheManager("myCacheName");
}
public void Benchmark(){
HighPerformanceTimer timer = new HighPerformanceTimer();
timer.Start();
myObject o = (myObject)_cache.GetData(myCacheKey);
timer.Stop();
Response.Write(timer.GetAsStringInMilliseconds());
}
Run Code Online (Sandbox Code Playgroud)
.NET 4.0缓存
System.Runtime.Caching.MemoryCache _cache;
public void InitCache(){
_cache = new MemoryCache("myCacheName");
}
public void Benchmark(){
HighPerformanceTimer timer = new HighPerformanceTimer();
timer.Start();
myObject o = (myObject)_cache.Get(myCacheKey);
timer.Stop();
Response.Write(timer.GetAsStringInMilliseconds());
}
Run Code Online (Sandbox Code Playgroud)
基准测试执行1000次以计算获取对象的平均时间,以确保测试的可靠性.计时器是我使用的自定义计时器,任何计时器计数毫秒都应该这样做.
有趣的是,"myObject"有很多引用.如果涉及任何序列化,我就会理解为什么这个对象的性能不同(比如在分布式缓存中),但这些都是进程中的缓存,理论上应该可以在没有很多重大差异的情况下工作.
我需要在我的项目中使用日志库,并考虑在Enterprise Logging Block与NLog vs log4net之间.我在比较中发现了一些链接,但大多数链接已经很老了,并抱怨没有新版本的log4net等等.
任何人都建议根据当前数据在易用性,易配置性,性能,可扩展性等方面哪一个更好.