asp.net core 宿主於windows程序


工作需要,我想在一個windows程序中提供webAPI的來提供打印服務。於是想到將asp.net core做的webapi放在windows上。今天周日,但又冷又下雨,哪也不去了。那就在家為公司的方案做一些技術調研吧。

asp.net core是可能跑在命令行下的。於是想能否直接轉為一個windows程序呢?是可以的,項目的選項就有,只是不徹底。就是無法添加新的Form。於是點擊項目文件,看其文本,修改為類似以下形式,就變成一個真正的winform項目。不過在2019會有錯誤,在這種項目下添加的Form,打開設計界面打開會報錯。所以winform還在放在其他項目吧。

 

有博主將asp.net core項目以引用的方式添加到wpf的程序里,在wpf里直接調用。不過我使用winform項目引用添加asp.net core項目時,也會報上面所說的一樣的錯誤。於是,我將asp.net core轉為winform項目后,作為主項目使用。另建一個winform項目編譯所有的Form,以引用的形式添加到主項目。

net5有注入,所以我就用net5開始了我的摸索。注入的知識可以看以下地址

https://www.cnblogs.com/artech/p/net-core-di-06.html

先定義兩個交互的接口

namespace WebApi.Interface
{
    /// <summary>
    /// 宿主創建
    /// </summary>
    public interface IMyApiHost
    {
        Microsoft.Extensions.Hosting.IHost BuildHost(IFormUI formUI);
    }
    /// <summary>
    /// 主UI界面
    /// </summary>
    public interface IFormUI
    {
        string SayHello(string name);
        string[] GetCommandArgs();
    }
}
View Code

IMyApiHost用於啟動一個asp.net core的實例。其實以下整個過程就是將上面的IFormUI接口傳入asp.net core的注入系統中。

winform項目准備一個啟動器給主項目使用。

namespace WebApiTestOnWin.App
{
    /// <summary>
    /// 界面啟動器。
    /// </summary>
    public class UIStarter
    {
        public IServiceProvider ApplicationService { get; private set; }
        public IServiceProvider ScopedService { get; private set; }
       
        public void StartConfig(IMyApiHost apiHost)
        {            
            var services = new ServiceCollection();            
            services.AddSingleton<MainForm>();            
            services.AddSingleton(apiHost);

            ApplicationService = services.BuildServiceProvider();
            ScopedService = ApplicationService.CreateScope().ServiceProvider;
        }

        public Form BuildMainForm()
        {
            var mainWindow = ScopedService.GetRequiredService<MainForm>();
            return mainWindow;
        }
    }
}

對於winform來說IMyApiHost是未知的。以下是MainForm的部分代碼。原構造函數需要加上一個入參,以接收這個必要的IMyApiHost。。

namespace WebApiTestOnWin.App
{
    public partial class MainForm : Form,IFormUI
    {
        IMyApiHost myHost;
        //public Form1()
        //{
        //    InitializeComponent();
        //}
        public MainForm(IMyApiHost api)
        {
            InitializeComponent();
            this.myHost = api;            
        }        

        private void button1_Click(object sender, EventArgs e)
        {
            myHost.BuildHost(this).RunAsync();//啟動asp.net core
        }
        public string SayHello(string name)
        {
            if (this.InvokeRequired)
            {
                var result = this.BeginInvoke(new SayHandler(this.SayHello), new object[] { name });
                result.AsyncWaitHandle.WaitOne(-1);
                return (string)this.EndInvoke(result);
            }
            this.lblMsg.Text = name + " saying...";
            return $"hi! {name},it's form.";
        }
        public string[] GetCommandArgs()
        {
            return Environment.GetCommandLineArgs();
        }
//........
}
View Code

好了,winform項目准備好了。看看asp.net core如何使用這個UIStarter。

使用前,asp.net core需要准備IMyWebApiHost的實現。其實就是將asp.net core的啟動包裝起來,以備MainForm使用。

namespace WebApiSimpleSite
{
    public class MyWebApiHostBuilder : MarshalByRefObject, IMyApiHost
    {
        IFormUI myFormUI;
        IHost host;
        public Microsoft.Extensions.Hosting.IHost BuildHost(IFormUI formUI)
        {
            myFormUI = formUI;
            string[] args = formUI.GetCommandArgs();
            var builder = Host.CreateDefaultBuilder(args);           
            var host = builder.ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureServices((svc)=>svc.AddSingleton(myFormUI) );
                    webBuilder.UseStartup<Startup>();
                });
            return host.Build();
        }
    }
}

好了,IFormUI在asp.net core的注入系統中准備好了,Controller可以使用IFormUI來控制winform。以下是Hello方法測試了這個過程

namespace WebApiSimpleSite.Controllers
{
    [Route("api/[controller]")] [ApiController] public class PrintController : ControllerBase { IFormUI myFormUI; public PrintController(IFormUI formUI) { myFormUI = formUI; } [HttpGet] public string Hello(string yourname) { return myFormUI.SayHello(yourname); } } }

 

好了,最后一步,在asp.net core(已手工轉換為winform程序)中啟動MainForm

namespace WebApiSimpleSite
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //CreateHostBuilder(args).Build().Run(); //原啟動asp.net core的命令行代碼           
            UIStarter starter = new UIStarter();//引用winform后,使用其UIStarter
            starter.StartConfig(new MyWebApiHostBuilder());//將asp.net core的啟動器傳入,以完成其配置           
            Form formMain = starter.BuildMainForm();//創建主程序
            Application.Run(formMain);
        }
}

以下是程序運行效果。web程序已可控制了winform程序

作者聲明:本文只發布在“博客網”,未經作者同意,請勿轉載!謝謝!余映畫 2022-2-20


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM