13

我为我的 log4net 日志对象的初始化创建了一个包装类,以便更容易在 ThreadContext 中建立自定义属性。这发生在我与许多其他有用函数一起建立的类库中。为了加入所有各种库,我还使用“/internalize”开关向 ILMerge 添加了 AfterBuild 目标。

ILMerge 所针对的库中对这个初始化方法的所有引用似乎都可以正常工作。但是,当我在其他地方引用这个合并的库时。我的实现引发了保护级别错误。我尝试将各种内容添加到可选的排除 (/internalize:excludes.txt) 文件中,但这似乎不起作用。

示例 excludes.txt:

log4net.Config
log4net.ThreadContext
log4net.LogManager

其他人遇到过这个问题吗?

[编辑]:

这是代码:

 [assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Logging
{
    public static class Log4NetThreadContext
    {
        public static ILog Initialize(Type declaringType)
        {
            // Read from configuration
            XmlConfigurator.Configure();

            // Set Properties
            ThreadContext.Properties["ID"] = ...
                ...
                ...
                ...

            if(System.Diagnostics.Debugger.IsAttached)
            {
                // Special debugging logger
                return LogManager.GetLogger("DEBUG_MODE");
            }
            else
            {
                // Root logger
                return LogManager.GetLogger(declaringType);
            }
        }
    }
}

我正在像这样使用这段代码..

private static readonly Type declaringType = 
    MethodBase.GetCurrentMethod().DeclaringType;
private static readonly ILog log =
    Log4NetThreadContext.Initialize(declaringType);
...
log.Info("Something useful");

[编辑]:

这是我的 AfterBuild 目标

<Target Name="AfterBuild">
<CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
  <Output ItemName="AssembliesToMerge" TaskParameter="Include" />
</CreateItem>
<Message Text="MERGING: @(AssembliesToMerge->'%(Filename)')" Importance="High" />
<Exec Command="&quot;$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe&quot; /targetplatform:v2 /log /internalize:&quot;ilmerge.excludes.txt&quot; /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
<Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />

一般来说,是否有更好的方法来调试保护级别问题?

Log4NetThreadContext.Initialize(System.Type)' is inaccessible due to its protection level
4

2 回答 2

7

最终,最简单的做法是将 log4net 从 ilmerge 过程中完全排除,并将其作为依赖程序集进行维护。

因此,经过多次折磨,这里是“不那么明显”的解决方案..

毕竟不需要排除,真正的答案是使用/lib:[path]ilmerge 中的开关。

我更新了目标以从交换机AfterBuild中删除排除项。/internalize接下来,我添加了/lib将 log4net dll 的位置作为依赖引用传递的开关。它看起来像这样:

<Target Name="AfterBuild">
  <CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
    <Output ItemName="AssembliesToMerge" TaskParameter="Include" />
  </CreateItem>
  <Message Text="MERGING: @(AssembliesToMerge->'%(Filename)')" Importance="High" />
  <Exec Command="&quot;$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe&quot; /lib:..\packages\log4net.2.0.0\lib\net35-full\ /targetplatform:v2 /log /internalize /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
  <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>

此外,我添加了另一个目标,通过向<ILMerge />位于我的 .csproj 文件中的引用添加唯一元素来限制合并中包含的程序集列表

<Target Name="AfterResolveReferences">
  <Message Text="Filtering out ILMerge assemblies from ReferenceCopyLocalPaths..." Importance="High" />
  <ItemGroup>
    <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.ILMerge)'=='false'" />
  </ItemGroup>
</Target>

因此,参考元素按如下方式列出以适应:

...
<Reference Include="Ionic.Zip">
  <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
  <ILMerge>True</ILMerge>
</Reference>
<Reference Include="log4net">
  <HintPath>..\packages\log4net.2.0.0\lib\net35-full\log4net.dll</HintPath>
  <ILMerge>False</ILMerge>
...

将 ILMerge=False 值显式添加到开关可能有更好的(编程)替代方案,/lib但在我的情况下,由于只有一个排除项,因此就足够了。否则,您可能需要手动添加其他路径。

我列出的“AfterResolveReferences”技术归功于http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlessWithILMergeAndMSBuild.aspx

希望这可以帮助某人!

于 2013-01-31T20:48:04.287 回答
1

当我从远程位置运行代码时,这通常会发生在我身上。从远程位置访问配置文件时,.NET 存在权限问题。例如,网络共享上的代码存储库设置。

我只能通过将我的代码移动到本地硬盘来克服它(因为我没有管理员权限来将网络共享的安全性提升到“受信任”等)。

(请注意,这主要是 2005 年之前的 Visual Studio 版本的问题。我认为这在 2008 年以后已修复,因此它可能不会影响您。不过,您没有说您使用的是什么版本。)

于 2013-01-22T15:59:33.303 回答