当前位置: 首页 > news >正文

如何组织一个同时面向 UWP/WPF/.Net Core 控制台的 C# 项目解决方案

希望写一个小型工具,给自己和需要的人。考虑到代码尽可能的复用,我准备采用 .Net Standard 来编写大多数核心代码,并基于 .Net Core 编写跨平台控制台入口,用 WPF 编写桌面端 UI 入口,用 UWP 作为可上架商店的 UI 入口,然后用 Shared Project 共享 WPF 和 UI 的多数 UI 入口代码。

阅读本文将了解到如何在尽可能复用代码的情况下组织这样的 C# 解决方案。


工具型项目,选择了控制台

用 WPF 开发桌面 UI,因为其有强大的 .NET Framework 库在背后支持,外加方便而功能齐全的 XAML 开发环境,在用 C# 进行桌面应用程序开发的时候不失为一种优秀的选择。但微软却并不怎么重视 WPF,而一直投入较大资源在半死不活的 UWP 上,导致 WPF 现在有非常多的坑是在 UWP 上才解的。然而,微软却并没有好好运营 UWP,以至于其开发者急剧减少,再在上面投入太多精力投入产出比显得太低。

.NET Framework 是个优秀的框架,可是与 Windows 桌面端绑得太死,以至于在当下多平台发展得都不错的情况下失去了大多数的竞争力。但是 .NET Core 解决了这个问题。然而谈到 UI 的跨平台,就是一个巨大的投入和难以见底的坑,以至于基于 .NET Core 且跨平台的 UI 框架目前依然没有出现。

毕竟只是工具型项目,并不想去动用大型 UI 框架 Xamarin/Unity,以至于写一个 .NET Core 控制台程序成了小型工具型项目的最佳解决方案了。

工具型项目是任务导向的,能完成任务为最终目的。控制台与配置文件的配合不仅足以完成任务,还为自动化或其他工具集成提供了方便。这里提供 UI 只是为了方便此工具用户的初学使用和理解。

组织一个 C# 解决方案

我们总共涉及到的 Visual Studio 项目类型有这五个:
- 类库(.NET Standard)
- 共享项目
- 控制台应用(.NET Core)
- WPF 应用(.NET Framework)
- 空白应用(通用 Windows)

.NET Standard 和共享项目是默认就装上的,但其他三个却不是。需要在 Visual Studio 安装界面中额外勾选:
- 用于安装通用 Windows 项目,如果你对此不感兴趣,忽略即可
这里写图片描述
- 用于安装 WPF 应用,如果你对此不感兴趣,忽略即可
这里写图片描述
- 用于安装 .NET Core 项目,这是跨平台的重点,建议安装
这里写图片描述

在 Visual Studio 中创建一个解决方案的时候依次添加这五种项目。
- 我们的主要逻辑代码全在 .NET Standard 项目中。这里包含了完整的功能实现,可以脱离其他四种实现完整功能。
- .NET Core 控制台项目仅仅作为入口,引用 .NET Standard 的项目,将用户输入的命令转为具体的函数调用。
- 共享项目的代码主要是 UI 或 UI 辅助代码,例如控制 UI 的逻辑和 ViewModel。
- UWP 和 WPF 项目仅包含 UI(XAML)和必要的不一致的 UI 控制逻辑,通过链接的方式将共享项目中的代码引入如何链接?。
- 其他的工具库当然也是需要的,但为了通用,建议优先选择 .NET Standard 的库。

这样,项目在 Visual Studio 中看起来大概是这样的:
这里写图片描述

相关文章:

  • 出让执行权:Task.Yield, Dispathcer.Yield
  • 如何防止后台线程抛出的异常让程序崩溃退出
  • CaptureMouse/CaptureStylus 可能会失败
  • 使用 ExceptionDispatchInfo 捕捉并重新抛出异常
  • 使用 Task.Wait()?立刻死锁(deadlock)
  • 如何实现一个可以用 await 异步等待的 Awaiter
  • WPF 同一窗口内的多线程 UI(VisualTarget)
  • WPF 和 UWP 中,不用设置 From 或 To,Storyboard 即拥有更灵活的动画控制
  • 从 “x is null 和 x == null” 的区别看 C# 7 模式匹配中常量和 null 的匹配
  • 使用不安全代码将 Bitmap 位图转为 WPF 的 ImageSource 以获得高性能和持续小的内存占用
  • WPF 跨应用程序域的 UI(Cross AppDomain UI)
  • 将 UWP 的有效像素(Effective Pixels)引入 WPF
  • 用动画的方式画出任意的路径(直线、曲线、折现)
  • 使 WPF 支持触摸板的横向滚动
  • NullReferenceException,就不应该存在!
  • (三)从jvm层面了解线程的启动和停止
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【mysql】环境安装、服务启动、密码设置
  • 2019年如何成为全栈工程师?
  • Js基础知识(四) - js运行原理与机制
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • overflow: hidden IE7无效
  • Rancher-k8s加速安装文档
  • spring + angular 实现导出excel
  • Spring Boot MyBatis配置多种数据库
  • 多线程 start 和 run 方法到底有什么区别?
  • 关于for循环的简单归纳
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 使用 @font-face
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 双管齐下,VMware的容器新战略
  • 因为阿里,他们成了“杭漂”
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • kubernetes资源对象--ingress
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • #stm32整理(一)flash读写
  • #微信小程序:微信小程序常见的配置传值
  • $$$$GB2312-80区位编码表$$$$
  • (k8s中)docker netty OOM问题记录
  • (pytorch进阶之路)扩散概率模型
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二)Eureka服务搭建,服务注册,服务发现
  • (二十四)Flask之flask-session组件
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (三)elasticsearch 源码之启动流程分析
  • (三)mysql_MYSQL(三)
  • (十三)Flask之特殊装饰器详解
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • ******之网络***——物理***
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET和.COM和.CN域名区别
  • .net下简单快捷的数值高低位切换