瀏覽標籤:

.NET Core

[C#][DI] 相互依賴造成循環注入死結

問題緣由

最近在寫 .NET Core 的時候遇到了一個問題

A circular dependency was detected for the service of type 'WebApplication1.Service.A1Service'

 

A1Service

public class A1Service
{
    private readonly string guid = null;
    private readonly A2Service _a2Service = null;

    public A1Service(A2Service a2Service)
    {
        _a2Service = a2Service;

        if (guid == null)
        {
            guid = Guid.NewGuid().ToString();
        }
    }

    public void Run()
    {
        Console.WriteLine("A1Service: " + guid);
    }

    public void RunOther()
    {
        _a2Service.Run();
    }
}

 

這是網路教學文章上常見的從建構子中依賴注入 A2Service 的程式
接著我們再來看看另外一支程式

A2Service

public class A2Service
{
    private readonly string guid = null;
    private readonly A1Service _a1Service = null;

    public A2Service(A1Service a1Service)
    {
        _a1Service = a1Service;

        if (guid == null)
        {
            guid = Guid.NewGuid().ToString();
        }
    }

    public void Run()
    {
        Console.WriteLine("A2Service: " + guid);
    }

    public void RunOther()
    {
        _a1Service.Run();
    }
}

 

 

這裡就發生了一個循環依賴的問題 A1Service 在建構子中注入了 A2Service,而 A2Service 也在建構子中注入了 A1Service,造成兩個物件互相依賴造成 Exception

解決方法

改成不直接在建構子中注入 Service ,改注入 IServiceProvider,再利用 GetService 這個方法來取得物件,這樣就可以順利解決這個問題囉。

A3Service

public class A3Service
{
    private readonly string guid = null;
    private readonly IServiceProvider _serviceProvider = null;

    public A3Service(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;

        if (guid == null)
        {
            guid = Guid.NewGuid().ToString();
        }
    }

    public void Run()
    {
        Console.WriteLine("A3Service: " + guid);
    }

    public void RunOther()
    {
        _serviceProvider.GetService<A4Service>().Run();
    }
}

 

A4Service

public class A4Service
{
    private readonly string guid = null;
    private readonly IServiceProvider _serviceProvider = null;

    public A4Service(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;

        if (guid == null)
        {
            guid = Guid.NewGuid().ToString();
        }
    }

    public void Run()
    {
        Console.WriteLine("A4Service: " + guid);
    }

    public void RunOther()
    {
        _serviceProvider.GetService<A3Service>().Run();
    }
}

 

       

[.NET Core] 將 NET Core 部署至 Ubuntu Server 16.04

最近裝了個Linux Server想來玩玩看NET Core並佈署到上面,結果發現好多眉眉角角,網路上的文件似乎有點舊讓我一直撞牆撞不停,經過了幾個小時的煎熬最後終於成功了,這裡筆記一下方便下次使用…

首先按照 官網 提供的步驟進行安裝如下:

  1. 加入apt-get來源
    sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
    sudo apt-get update
  2. 開始安裝
    sudo apt-get install dotnet-dev-1.0.4
  3. 建立一個空資料夾
    mkdir HelloWebApp
    cd HelloWebApp
  4. 初始化MVC專案
    dotnet new mvc

    Templates清單:

    Templates                 Short Name      Language      Tags
    ----------------------------------------------------------------------
    Console Application       console         [C#], F#      Common/Console
    Class library             classlib        [C#], F#      Common/Library
    Unit Test Project         mstest          [C#], F#      Test/MSTest
    xUnit Test Project        xunit           [C#], F#      Test/xUnit
    ASP.NET Core Empty        web             [C#]          Web/Empty
    ASP.NET Core Web App      mvc             [C#], F#      Web/MVC
    ASP.NET Core Web API      webapi          [C#]          Web/WebAPI
    Solution File             sln                           Solution
  5. 檢查套件是否遺失並安裝
    dotnet restore
  6. 安裝Apache反向代理(Reverse-Proxy)
    sudo a2enmod proxy
    sudo a2enmod proxy_http
    sudo a2enmod proxy_ajp
    sudo a2enmod rewrite
    sudo a2enmod deflate
    sudo a2enmod headers
    sudo a2enmod proxy_balancer
    sudo a2enmod proxy_connect
    sudo a2enmod proxy_html
  7. 設定000-default.conf
    <VirtualHost *:80>
    	ProxyPreserveHost On
    	ProxyPass / http://127.0.0.1:5000/
    	ProxyPassReverse / http://127.0.0.1:5000/
    </VirtualHost>
  8. 重新啟動Apach並啟動.NET Core專案
    sudo service apache2 restart
    dotnet run
  9. 完成 !!
    2017-03-14-00_24_31-home-page-hellowebapp

 

 

  • 2017/05/24 開啟啟動&背景執行
    新增:/etc/systemd/system/kestrel-hellomvc.service

    [Unit]
    Description = https://blog.exfast.me/
    
    [Service]
    WorkingDirectory = /home/user/HelloWebApp/
    ExecStart = /usr/bin/dotnet run /home/user/HelloWebApp/HelloWebApp.dll
    Restart = always
    # Restart service after 10 seconds if dotnet service crashes
    RestartSec = 10
    SyslogIdentifier = dotnet-example
    User = user
    Environment = ASPNETCORE_ENVIRONMENT = Production 
    
    [Install]
    WantedBy = multi-user.target

    指令:

    sudo systemctl stop kestrel-hellomvc
    sudo systemctl disable kestrel-hellomvc
    sudo systemctl enable kestrel-hellomvc
    sudo systemctl start kestrel-hellomvc
    sudo systemctl status kestrel-hellomvc

     

來源:

  1. https://www.microsoft.com/net/core#linuxubuntu
  2. How To Use Apache HTTP Server As Reverse-Proxy Using mod_proxy Extension
  3. Asp.Net Core 发布和部署( MacOS + Linux + Nginx )
  4. Publish to a Linux Production Environment
  5. Using Apache web server as a reverse proxy