簡體   English   中英

Autofac:如何加載引用但未直接使用的程序集

[英]Autofac: How to load assemblies that are referenced but not directly used

我們使用Autofac for DI創建了一個WebApi解決方案。 我們將autofac的引導分解為一個單獨的項目。 這樣,我們的WebApi項目僅引用我們的Bootstrap和Contracts項目。 然后我們的引導項目引用所有其他組件並將所有內容連接在一起。 我喜歡這種設計用於分離關注點。

我們可以按如下方式手動加載我們的程序集 - 我們的“AutofacModule”類包含注冊每個模塊(程序集)的必要信息。

ContainerBuilder builder = new Autofac.ContainerBuilder();
builder.RegisterModule(new Business.AutofacModule());
builder.RegisterModule(new Data.AutofacModule());
builder.RegisterModule(new Services.AutofacModule());
etc...

這有效,但需要對每個程序集進行硬編碼。 我們試圖使這個動態化,以便我們可以循環遍歷所有引用的程序集,如下所示。

var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
foreach (var assembly in assemblies)
{
    builder.RegisterAssemblyModules(assembly);
}

這應該有效,但不行。 問題是.Net確定在引導程序項目中實際上沒有使用各種程序集而不加載它們(試圖優化?)。 所以我們的一些程序集從未加載過。

我還嘗試了以下循環bin目錄來查找所有程序集。 但是,在編譯期間,.Net不會將未引用的程序集移動到bin目錄中,因此它們也不存在。

string assemblyPath = System.IO.Path.Combine(
    System.AppDomain.CurrentDomain.BaseDirectory, "bin");
var allAssemblies = new List<Assembly>();
foreach (string dll in Directory.GetFiles(assemblyPath, "*.dll"))
{
    allAssemblies.Add(Assembly.LoadFile(dll));
}

我已將程序集設置為“復制本地”,但無效。 我讀到了一個Copy Local錯誤,並嘗試了一些不起作用的解決方法。

有沒有人能夠解決這個問題? 看起來Autofac會提供一個解決方案,但我發現他們的文檔上只有一個待辦事項頁面: http//autofac.readthedocs.org/en/latest/faq/isolate-autofac.html

以下兩個問題是相似的,但是所提出的解決方案都沒有克服所需程序集不在bin目錄中的事實。

並非所有程序集都從bin文件夾加載到AppDomain中

即使未在代碼中明確使用,也要加載所有引用的程序集.NET

最后,我很好奇,這是一個Autofac特定的問題嗎? 其他DI容器如何解決這個問題? 我發現了NInject的類似問題。 加載未引用的dll MVC Ninject

這應該對你有幫助。 它接受bin文件夾中的所有程序集,從名稱MyModule開始。

   //builder.RegisterType(typeof(IFoo)).AsImplementedInterfaces();
        ContainerBuilder builder = new ContainerBuilder();

        string[] assemblyScanerPattern = new[] { @"MyModule.*.dll"};

        // Make sure process paths are sane...
        Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);

        //  begin setup of autofac >>

        // 1. Scan for assemblies containing autofac modules in the bin folder
        List<Assembly> assemblies = new List<Assembly>();
        assemblies.AddRange(
            Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories)
                     .Where(filename => assemblyScanerPattern.Any(pattern => Regex.IsMatch(filename, pattern)))
                     .Select(Assembly.LoadFrom)
            );


        foreach (var assembly in assemblies)
        {
            builder.RegisterAssemblyTypes(assembly )
                .AsImplementedInterfaces();
        }
        var container = builder.Build();

這將加載那些甚至沒有引用的程序集。

var assemblies = Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll", SearchOption.TopDirectoryOnly)
   .Where(filePath => Path.GetFileName(filePath).StartsWith("your name space"))
   .Select(Assembly.LoadFrom);

var builder = new ContainerBuilder();

builder.RegisterAssemblyTypes(assemblies.ToArray())
   .Where(t => typeof(ITransientDependency).IsAssignableFrom(t))
   .AsImplementedInterfaces();

//簡答

您是否看過這個: http//docs.autofac.org/en/latest/faq/iis-restart.html看起來您可以掃描引用的程序集並強制它們加載。

//建議(或意見,如果你喜歡)

就個人而言,我不會加載那些只是為了能夠為引導創建一個單獨的項目而不會被使用的程序集。 我沒有看到在它自己的項目中擁有它的好處。 請記住,DI就是這樣,你正在注入“那個”項目的依賴項。 每個項目都可以擁有自己的依賴項,關注點的分離來自bootstrapping類,而不是它自己的項目。 如果您需要將您的業務邏輯項目分解為公司中其他項目將使用的nuget包,您不希望他們也必須下載DI項目包,而現在又需要其他可能永遠不會使用的包。 如果您的依賴項包含在需要它們的項目中,它將變為模塊化和可擴展的。 這部分答案當然值得商榷,但至少應予以考慮。

如果您的解決方案中有多個項目,每個項目都有自己的IoC容器類,請使用以下內容加載所有程序集,然后在該程序集中注冊每個模塊。

這是ContainerBuilder的擴展方法。

public static class ContainerBuilderExtensions
{
    public static void ScanAssembly(this ContainerBuilder builder, string searchPattern = "SolutionName.*.dll")
    {
        var path = AppDomain.CurrentDomain.BaseDirectory;
        foreach (var assembly in Directory.GetFiles(path, searchPattern).Select(Assembly.LoadFrom))
        {
            builder.RegisterAssemblyModules(assembly);
        }
    }
}

可以在ContainerBuilder的實例上調用上面的內容,如下所示:

builder.ScanAssembly()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM