前言

今天研究了在 WPF 中使用 SelfHost 自宿主。 具体的功能是,在 WPF 中使用自宿主服务,外部调用服务的 API,在 API 里面操作窗体的显示等。

技术点

  1. 在 WPF 中集成 SelfHost
  2. API 和窗体间交互

一、集成 SelfHost

现在已有的资料中,使用 SelfHost 做自宿主服务的基本都是用控制台实现 WebAPI 的功能,或者在 WinFrom 中集成。WFP 和这些还是有挺大的区别。 我这里是参考了这个文章:Self-Host 
具体的步骤如下: 
1. 添加引用包 
在 NuGet 中添加 “Microsoft.AspNet.WebApi.SelfHost”和“Microsoft.AspNet.WebApi.Cors”库,其他依赖的类库基本都会添加进来 
2. 初始化服务 
新建类 “InitConfig”在类里添加初始化自宿主的一些设置。 
具体代码如下:

        public static HttpSelfHostConfiguration InitSelfHostConfig(string baseAddress)
{
// 配置 http 服务的路由
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(baseAddress);
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional }
); // 设置跨域
var cors = new EnableCorsAttribute("*", "*", "*"); //跨域允许设置
config.EnableCors(cors); config.Formatters
.XmlFormatter.SupportedMediaTypes.Clear(); //默认返回 json
config.Formatters
.JsonFormatter.MediaTypeMappings.Add(
new QueryStringMapping("datatype", "json", "application/json")); //返回格式选择
config.Formatters
.XmlFormatter.MediaTypeMappings.Add(
new QueryStringMapping("datatype", "xml", "application/xml")); //json 序列化设置
config.Formatters
.JsonFormatter.SerializerSettings = new
Newtonsoft.Json.JsonSerializerSettings()
{
//NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
DateFormatString = "yyyy-MM-dd HH:mm:ss" //设置时间日期格式化
};
return config;
}

  这里返回的会在新建服务的时候调用

3. 添加 Program 类

WPF 默认是没有这个类的,需要自己手动添加这样的一个类。

这个类的代码:

        /// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
string baseAddress = string.Format("http://{0}:{1}/",
System.Configuration.ConfigurationManager.AppSettings.Get("Domain"),
System.Configuration.ConfigurationManager.AppSettings.Get("APIPort"));
using (var server = new HttpSelfHostServer(InitConfig.InitSelfHostConfig(baseAddress)))
{
server.OpenAsync().Wait();
Console.WriteLine(String.Format("host 已启动:{0}", baseAddress));
App app = new App();
app.Run();
}
}

  其中 baseAddress 是拼接的服务地址,同时在“属性”里设置项目的启动对象为“Program”。

后面添加一些 API 进行测试。

    public class HomeController : ApiController
{
[HttpGet]
public object Get()
{
return new { code = 1, msg = "OK HomeController" };
}
}

  运行项目在浏览器输入对应的地址即可。

二、API 和窗体交互

由于 API 是另外定义的类。不能直接操作窗体,新建窗体实例、传递窗体都有问题。

这里用的是“事件跨类调用”,参考了“C#通过事件跨类调用WPF主窗口中的控件”。

新建一个类继承“EventArgs”:

    public class MessageArgs : EventArgs
{
public MessageArgs(string comMessage)
{
this.ComMessage = comMessage;
} public string ComMessage { get; set; } }

  在 ApiController 中定义事件、触发事件:

    public class PlayController : ApiController
{ public static event EventHandler<MessageArgs> PartEvent; //定义在 PlayController 中的一个事件,参数是MessageArgs对象 public static void InFunction(string comMessage)
{
var messageArg = new MessageArgs(comMessage);
PartEvent?.Invoke(null, messageArg); //触发事件,执行所有注册过的函数
} [HttpGet]
public object Play(string comd)
{
InFunction(comd);
return new { code = 0, msg = "成功播放!" };
}
}

  在窗体中注册上面的事件,以及里面的具体逻辑:

        public MainWindow()
{
InitializeComponent(); PlayController.PartEvent += OnStep; //将该类中的函数注册到Monitor静态类的PartEvent事件中。
} /// <summary>
/// 订阅 Monitor 的PartEvent事件,当触发PartEvent事件时(可能并不在类MainWindow对象中),被注册的函数就行做出相应的响应。
/// </summary>
/// <param name="sender"></param>
/// <param name="message"></param>
public void OnStep(Object sender, MessageArgs message)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
DoCommand(message.ComMessage);
}));
}

  这样,API 接可以和窗体进行通信。

总结

到这里,整个的功能都已经完成。

在自己预研的时候,也是一步一步的。从集成,一点点的改进。

到API和窗体通信,也查了看了一些方法。最终选的这些思路。

WPF + SelfHost 实现窗体自宿主(API,API和窗体通信)的更多相关文章

  1. 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作

    原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, ...

  2. windows service宿主web api使用"依赖注入"和“控制反转”的技术实践

    前言 自从几年前抛弃wcf,使用web api 来做服务器端开发之后,就不再迷惑了.但是因为本来从事传统行业管理软件开发,一般都以分布式应用开发为主.纯BS还是比较少,于是比较喜欢用windows s ...

  3. WPF换肤之二:可拉动的窗体

    原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知 ...

  4. Jasper:API / API 策略和最佳做法

    ylbtech-Jasper:API / API 策略和最佳做法 1.返回顶部 1. API 策略和最佳做法 Cisco Jasper 已经建立了一项 API 公平使用策略,确保所有 Control  ...

  5. WPF 设置类库项目为启动项,设置窗体跟随。

    原文:WPF 设置类库项目为启动项,设置窗体跟随. 1.添加用于启动的类Program.cs,需要一个静态的Main函数入口. using System; using System.Windows; ...

  6. WPF最小化窗体后激活函数显示不了窗体

    WPF最小化窗体后激活函数显示不了窗体 今天测试小哥给我提了一些问题,其中一个问题是这样的,点击web端的一个链接,是能启动本地的一个应用程序的,如果本地应用程序已启动(通过tcp进程间通信),那么应 ...

  7. vue中的import {} from '@/api/api'

    例:import {queryDepartTreeList, searchByKeywords} from '@/api/api' 首先查看vue.config.js文件,在这个文件里面定义了定义了@ ...

  8. DirectUI中模态对话框和菜单的原理(自己控制整个Windows消息循环。或者,用菜单模拟窗体打开时用SetCapture取得控制权,一旦窗体收到WM_CAPTURECHANGED消息就把窗体退出)

    经常有人问关于模态对话框和系统菜单内部实现原理方面的问题, 因为系统通过API隐藏了太多细节,这2个问题确实令初学者甚至是有经验的开发者困扰, 下面是我个人的一些经验总结. 先说模态对话框,外部看模态 ...

  9. Delphi 使窗体Showmodal后可以操作其他窗体

    对话框ShowModal之后不能操作其它窗口,实际上是因为Windows Disable了其它窗口.所以当你需要在模态对话框中访问其它已经可见的窗口时,需要用EnableWindow API来激活对应 ...

随机推荐

  1. 面试官:知道你的接口QPS是多少么?(转)

    面试官:知道你的接口QPS是多少么? 原创: 孤独烟 孤独烟 9月24日 引言 大家好,我是渣渣烟. 我又来水文章了.这篇文章我个人感觉含金量不是太大,大概5分钟左右就能看完!其实大家都知道,我不爱写 ...

  2. LeetCode 131. 分割回文串(Palindrome Partitioning)

    131. 分割回文串 131. Palindrome Partitioning 题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. LeetC ...

  3. 总结IDEA和VS常用实用的快捷键

    整理了我一般撸码时使用下面两个IDE最常用到的快捷键: IntelliJ IDEA: 快捷搜索:Ctrl+F (Match Case:区分大小写,Words:全字匹配,Regex:正则匹配) 批量替换 ...

  4. 17 JQuery高级----学习笔记

    1. 动画(1) 三种方式显示和隐藏元素 <1> 默认显示和隐藏方式 1. show([speed,[easing],[fn]]) 1. 参数: 1. speed:动画的速度.三个预定义的 ...

  5. 关于MSVCR100.dll、MSVCR100d.dll、Msvcp100.dll、abort()R6010等故障模块排查及解决方法

    一.常见故障介绍 最近在开发相机项目(项目细节由于公司保密就不介绍了),程序运行5个来月以来首次出现msvcr100.dll故障等问题,于是乎开始了分析之路,按照度娘上的一顿操作,期间也是出现了各种不 ...

  6. C++类的组合、前向引用声明

    3.5类的组合 Part1.应用背景 对于复杂的问题,往往可以逐步划分为一系列稍微简单的子问题. 解决复杂问题的有效方法是将其层层分解为简单的问题组合,首先解决简单问题复杂问题也就迎刃而解了. 在面向 ...

  7. 数据结构与算法(Python)

    数据结构与算法(Python) Why? 我们举一个可能不太恰当的例子: 如果将最终写好运行的程序比作战场,我们码农便是指挥作战的将军,而我们所写的代码便是士兵和武器. 那么数据结构和算法是什么?答曰 ...

  8. SAS学习笔记58 单元格格式化设计

    单元格行_row_ 对于行单元格,主要就通过_row_这么一个自动变量的方式,来对单元格所有行进行格式化设计 例如,对性别为“男”的单元格所在行颜色设定为红色: 单元格列_col_ 将_row_改成_ ...

  9. 将ftp目录映射为本地盘符

    1.ftpuser 下载安装FTPUSE下载地址:http://www.ferrobackup.com/ftpuse/ 创建  FTPUSE F: www.xx.com pwd  /USER:admi ...

  10. Java调用WebService方法总结(2)--JAX-WS调用WebService

    用JAX-WS(Java API for XML Web Services)调用WebService不需要引入其他框架,都是JDK自带的:文中所使用到的软件版本:Java 1.8.0_191.Dom4 ...