Nic*_*erb 13 c# log4net ilmerge
我为log4net日志记录对象的初始化创建了一个包装类,以便更容易在ThreadContext中建立自定义属性.这发生在我已经建立的类库中以及许多其他有用的函数中.为了加入所有各种库,我还使用'/ internalize'开关向ILMerge添加了一个AfterBuild目标.
这种初始化方法的所有引用内由ILMerge针对性库似乎工作就好了.但是,当我在其他地方引用这个合并的库时.我的实现会引发保护级错误.我已经尝试向可选的exclude(/internalize:excludes.txt)文件中添加各种内容,但这似乎不起作用.
示例excludes.txt:
log4net.Config
log4net.ThreadContext
log4net.LogManager
Run Code Online (Sandbox Code Playgroud)
其他人遇到过这个问题吗?
[编辑]:
这是代码:
[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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用这样的代码..
private static readonly Type declaringType =
MethodBase.GetCurrentMethod().DeclaringType;
private static readonly ILog log =
Log4NetThreadContext.Initialize(declaringType);
...
log.Info("Something useful");
Run Code Online (Sandbox Code Playgroud)
[编辑]:
这是我的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=""$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe" /targetplatform:v2 /log /internalize:"ilmerge.excludes.txt" /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) "@(IntermediateAssembly)" @(AssembliesToMerge->'"%(FullPath)"', ' ')" />
<Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
Run Code Online (Sandbox Code Playgroud)
通常是否有更好的方法来调试保护级别问题?
Log4NetThreadContext.Initialize(System.Type)' is inaccessible due to its protection level
Run Code Online (Sandbox Code Playgroud)
最终,最简单的方法是将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=""$(ProgramFiles)\Microsoft\Ilmerge\Ilmerge.exe" /lib:..\packages\log4net.2.0.0\lib\net35-full\ /targetplatform:v2 /log /internalize /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) "@(IntermediateAssembly)" @(AssembliesToMerge->'"%(FullPath)"', ' ')" />
<Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
Run Code Online (Sandbox Code Playgroud)
另外,我添加了另一个目标,通过向<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>
Run Code Online (Sandbox Code Playgroud)
因此,列出的参考元素如此容纳:
...
<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>
...
Run Code Online (Sandbox Code Playgroud)
可能有一个更好的(编程式)替代方法,可以明确地将ILMerge = False值添加到/lib
交换机,但在我的情况下,由于只有一个被排除的项目就足够了.否则,您可能需要手动添加其他路径.
我列出的'AfterResolveReferences'技术可以归功于http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx
希望这有助于某人!