![](/img/trans.png)
[英]Autofac: How to load assemblies that are referenced but not directly used
[英]How can I dynamically load assemblies referenced by project, but not referenced in code
考慮一個引用NuGet包的.NET Core應用程序。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MyPackage" Version="1.0.0" />
</ItemGroup>
</Project>
如果我的代碼引用MyPackage
的類型,則將加載MyPackage
程序集。 如果我打印出所有引用或加載的程序集,則它將出現。
static void Main(string[] args)
{
// Because I have a reference to a type in MyPackage, the assembly
// is loaded and will be printed out by both foreach statements below.
var throwaway = typeof(MyPackage.Cars);
foreach (var an in Assembly.GetEntryAssembly().GetReferencedAssemblies())
{
WriteLine(an.Name);
}
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
WriteLine(assembly.FullName);
}
}
但是,如果我擺脫了那條throwaway
線,那么就不會加載程序集,因此GetReferencedAssemblies
或GetAssemblies
都不可用。
.NET Framework也存在相同的問題,通常的解決方法是讀取執行文件夾中的所有程序集並手動加載它們,例如:
Directory
.GetFiles(executingFolder, "*.dll", SearchOption.TopDirectoryOnly)
.Select(AssemblyLoadContext.Default.LoadFromAssemblyPath));
但是,.NET Core將從其他位置加載程序集(例如NuGet緩存-到目前為止,我還沒有找到有關新綁定過程的全面描述),因此上述方法將行不通。
因此,我的問題是:如何動態加載csproj文件引用的所有DLL(作為NuGet PackageReferences)。 我的用例相當神秘,因此我認為沒有其他機制可以使用。
好的,所以有人要問我的用例是什么,就在這里。
我們有一組定義消息的接口(IAuditEvent,IValidationEvent等)。 我們還為不同的序列化格式(Protobuf,XML,JSON等)提供了這些接口的各種實現。 其中每個都是單獨的NuGet程序包(MyMessages.Proto,MyMessages.Xml)。
我們有一個工廠將創建適當的實現( factory.Create<IAuditEvent>()
),但是它使用反射來完成此操作-例如,原型工廠找到實現IAuditEvent
的類,但也是Protobuf生成的類。 如果未首先加載程序集,則無法使用...
這一點實際上取決於策略。 如果您發現自己需要中介來反映和提供類型,則是考慮IoC容器的好時機。
在這里,您有幾種選擇:
Assembly.GetReferencedAssemblies不會返回您的程序集,因為它實際上沒有被引用。 如果您看一下exe文件的清單,您將找不到引用,就像編譯器對其進行了優化一樣。
AppDomain.GetAssemblies返回實際加載的程序集,請考慮:
static void Main(string[] args)
{
foreach (var an in Assembly.GetEntryAssembly().GetReferencedAssemblies())
{
WriteLine(an.Name);
}
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
WriteLine(assembly.FullName);
}
LoadType();
}
static void LoadType()
{
typeof(MyPackage.Cars);
}
在這種情況下,GetReferencedAssemblies調用的結果始終是相同的,但是GetAssemblies結果取決於您在調用GetAssemblies之前或之后放置LoadType的位置。
在構建服務器上,您不需要構建解決方案,而是發布解決方案,因此掃描程序集只是開發時間問題。 您可以在構建后事件中添加以下內容,也可以在項目中的dev目標中添加以下內容,並使用Daniel建議的方法之一:
dotnet發布“ $(ProjectPath)” --no-build -o“ $(TargetDir)”
但是,這遠非理想,希望您能提出更好的建議。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.