C#想要实现Electron那样混合桌面程序可以用以下几个库.
本文使用EdgeSharp
NanUI
Photino
Electron.NET
EdgeSharp
Chromely
EdgeSharp 可以直接使用HTML,
也可以配合Blazor、Razor 、SolidJs、Svelte、React、Vue、Angular等前端框架。
直接调用系统中Edge浏览器所配套的 WebView2,
无需像Electron那样打包整个浏览器内核,打包后的文件非常小。
更多强大的功能可以查看官方示例,本文只使用了最简单的HTML
EdgeSharp.Samples/win-32
直接 控制台项目 调用 win32 创建一个窗口, helloworld 程序打包后只有 1.5M !
本文中使用 Winform 打包后也是只有 1.5M 左右( js库都引用的cdn)
EdgeSharp.Samples/winform
EdgeSharp.Samples/wpf
EdgeSharp.Samples/angular-react-vue
创建后,删除其他文件,只保留 Program.cs
<PackageReference Include="EdgeSharp.Core" Version="0.9.0" />
<PackageReference Include="EdgeSharp.WinForms" Version="0.9.0" />
using System.ComponentModel;
using System.Windows.Forms;
using EdgeSharp.Core;
using EdgeSharp.Core.Configuration;
using EdgeSharp.Core.Defaults;
using EdgeSharp.Core.Infrastructure;
using EdgeSharp.WinForms;
using HelloEdgeSharp.Controller;
using Microsoft.Extensions.DependencyInjection;
namespace HelloEdgeSharp
{
internal static class Program
{
[STAThread]
static void Main()
{
try
{
Application.SetHighDpiMode(System.Windows.Forms.HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var appBuilder = new AppBuilder<Startup>();
ServiceLocator.Bootstrap(appBuilder);
var bowserForm = (BrowserForm)ServiceLocator.Current.GetInstance<IBrowserWindow>();
Application.Run(bowserForm);
appBuilder?.Stop();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}
public class Startup : WinFormsStartup
{
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
services.AddSingleton<IConfiguration, SampleConfig>();
services.AddSingleton<IBrowserWindow, SampleBrowserForm>();
// 注入 控制器
RegisterActionControllerAssembly(services, typeof(HelloController).Assembly);
}
public override void Initialize(IServiceProvider serviceProvider)
{
base.Initialize(serviceProvider);
}
}
internal class SampleConfig : Configuration
{
public SampleConfig() : base()
{
// 拦截 api 并导航到 Controller (用RegisterActionControllerAssembly注册控制器)
UrlSchemes.Add(new("http", "api", null, UrlSchemeType.ResourceRequest));
// 静态文件资源 拦截 导航到 wwwroot
UrlSchemes.Add(new("http", "app", "wwwroot", UrlSchemeType.HostToFolder));
// 设置 首页地址
StartUrl = "http://app/index.html"; ;
// 去掉窗口标题栏
//WindowOptions.Borderless = true;
}
}
internal class SampleBrowserForm : BrowserForm
{
public SampleBrowserForm()
{
Width = 1200;
Height = 900;
var executable = System.Reflection.Assembly.GetExecutingAssembly();
var iconStream = executable.GetManifestResourceStream("EdgeSharp.WinForms.Sample.edgesharp.ico");
if (iconStream != null)
{
Icon = new Icon(iconStream);
}
}
// 可以重写 各种生命周期
protected override void Bootstrap()
{
base.Bootstrap();
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
}
}
}
继承
ActionController
, 并添加ActionController
,ActionRoute
两个特性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EdgeSharp.Core.Network;
namespace HelloEdgeSharp.Controller
{
[ActionController(Name = "HelloController", Description = "测试控制器")]
public class HelloController : ActionController
{
public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Version { get; set; }
public string Url { get; set; }
}
public class Result<T>
{
public bool Succeeded { get; set; }
public T Data { get; set; }
public string Errors { get; set; }
}
[ActionRoute(Path = "/getFrameWorks")]
public Result<object> GetFrameWorks(int index, int size)
{
var list = new List<UserInfo>
{
new UserInfo()
{
Id = 1,
Name = "React",
Version = "v1",
Url = "http://www.react.com",
},
new UserInfo()
{
Id = 2,
Name = "Vue",
Version="v2",
Url = "http://www.vue.com",
}
};
return new Result<object>
{
Succeeded = true,
Data = new
{
Items = list,
TotalCount = 100,
}
};
}
}
}
html代码省略
这里是Js发起请求与C#交互的关键代码
// 在C# SampleConfig 中配置了UrlSchemeType.ResourceRequest,
// 会拦截这个域名 http://api/ 的请求
let instance = axios.create({
baseURL: "http://api/",
timeout: 15000,
});
// 发起get请求
instance.get("/getFrameWorks?index=1&size=2")
.then(r => {
// 成功拿到controller中返回的数据
console.log(r)
})
这样我们就得到了一个
HTML作为页面
,C#作为后端
的桌面程序