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

posted @ 2022-02-20 21:23  生命体验之kevin-Y  阅读(1060)  评论(4编辑  收藏  举报