log4net在编译时未通过validation

https://github.com/apache/log4net

我正在从上面的源代码编译log4net,但它没有通过validation:

[IL]:错误:[log4net.dll:log4net.Plugin.RemoteLoggingServerPlugin :: Attach] [offset 0x00000029]方法不可见。

代码还可以:

public interface ILoggerRepository { ... } public interface IPlugin { void Attach(ILoggerRepository repository); } public abstract class PluginSkeleton : IPlugin { public virtual void Attach(ILoggerRepository repository) { } } public class RemoteLoggingServerPlugin : PluginSkeleton { override public void Attach(ILoggerRepository repository) { base.Attach(repository); ... } } 

https://github.com/apache/log4net/blob/trunk/src/Plugin/IPlugin.cs

https://github.com/apache/log4net/blob/trunk/src/Plugin/PluginSkeleton.cs

https://github.com/apache/log4net/blob/trunk/src/Plugin/RemoteLoggingServerPlugin.cs

调查显示它无法调用RemotingServices.Marshal()

 override public void Attach(ILoggerRepository repository) { base.Attach(repository); // Create the sink and marshal it m_sink = new RemoteLoggingSinkImpl(repository); try { **RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink));** } catch(Exception ex) { LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex); } } 

但这里没有什么关键。 此外,调用任何类型的RemotingServices.Marshal()会导致相同的问题:

即使我将Attach()更改为:

 override public void Attach(ILoggerRepository repository) { RemotingServices.Marshal(null, null, typeof(int)); } 

有人能发现问题是什么吗?

问题与引入.NET 4 Level 2透明度的事实有关。 (有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/dd233102.aspx 。)

方法override public void Attach(ILoggerRepository repository)缺少SecuritySafeCriticalAttribute 。 添加属性:

 #if NET_4_0 [System.Security.SecuritySafeCritical] #endif override public void Attach(ILoggerRepository repository) { // ... } 

将使ILvalidation通过。 (有关详细信息,请参阅: http : //msdn.microsoft.com/en-us/library/bb397858.aspx 。)

更新:为了更清楚地说明validation失败的原因(通过阅读所提供的链接中的文章可能无法立即明确),这里有一个简短的解释。

RemotingServices.Marshal已应用[SecuritySafeCritical]属性。 因此可以假设允许从透明方法调用方法。 但是, RemotingServices.Marshal返回System.Runtime.Remoting.ObjRef类型的对象,并且所述类型使用[SecurityCritical]属性进行注释。
如果log4net代码将在本地变量中存储对返回值的引用,则代码分析将检测错误并发出CA2140警告(“透明代码不得引用安全关键项”)。
现在显然在安全透明度规则下,如果被调用方法返回安全关键类型,透明方法可能不会调用安全性安全关键方法,即使透明方法不存储对返回对象的引用,如下面的示例所示:

 public class TransparencyRulesDemo { [SecuritySafeCritical] public void SafeGetCritical() { GetCritical(); } public void TransparentGetCritical() { // Below line will trigger a CA2140 warning if uncommented... // var critical = GetCritical(); // ...the following line on the other hand will not produce any warning // but will lead to IL verification errors and MethodAccessExceptions if // called from transparent code. GetCritical(); } [SecuritySafeCritical] public Critical GetCritical() { return new Critical(); } } [SecurityCritical] public class Critical { } 

这顺便说一下。 使RemotingServices.Marshal上的[SecuritySafeCritical]属性变得毫无意义。