"Xaml+C#"桌面客户端跨平台初体验

"Xaml+C#"桌面客户端跨平台初体验

前言

  随着 .Net 5的到来,微软在 .Net 跨平台路上又开始了一个更高的起点。回顾.Net Core近几年的成果,可谓是让.Net重生了一次.

  Asp .Net Core跨平台解决了Windows服务器昂贵的费用和不能长时间待机的问题,让Asp程序能够跑在Linux甚至Mac上。从博客园里.Net分类可以看到,每天都可以涌现大批Asp .Net Core的技术文章,越来越多的开发者或者公司开始尝试这个船新的跨平台框架。

  然鹅,Asp的跨平台是能够使用html作为UI,C#作为后台代码完成的,html本来就是原生支持跨平台的语言。如果要到达在客户端方面的跨平台,仍需要走很长一段路。

  早些年的时候。微软使用钞能力收购了移动客户端跨平台开发的大佬Mono,并组建了新的Xamarin,一次开发就可以生成Android,iOS,UWP平台的App,但也仅仅停留在移动客户端跨平台。同样在民间一些大佬的努力下,也创造出了很多PC跨平台的轮子,比如:Electron.Net,GTK#,Qt#等等,这些框架都是使用Html或者Mono平台的内容达到UI跨平台的,而今天我则要推荐一款新的跨平台方案AvaloniaUI。

准备

  • 一个Linux的机器
      这里推荐使用windows 10下的linux子系统,可以快速的在windows上操作linux子系统的文件目录,用来快速上传编译的程序到linux。详细操作可以看这篇文章启用Windows10的Linux子系统并安装图形界面。
      当然使用实体机,或者服务器都可以。总之最终目的就是有一个可以连接带图形化界面的Linux系统。

  • 安装.Net Core Runtime
      微软官方给出了在Ubutnu安装.Net Core的方法,这里我以Ubuntu为例,其他发行版本使用对应的包管理命令

1.注册 Microsoft 密钥和源

wget http://packages.microsoft.com/config/ubuntu/19.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

2.安装.Net Core 3.1 Runtmime

sudo apt-get update
sudo apt-get install apt-transport-http
sudo apt-get update
sudo apt-get install dotnet-runtime-3.1

    更多详情可参考Microsoft Docs :Ubuntu 19.04 包管理器 - 安装 .NET Core。

  • 安装VS拓展

    如果VS拓展下载太慢,可以使用下面的网盘链接下载。

链接: http://pan.baidu.com/s/1A_gwdiH8EZrgVWLWIhJkXQ 提取码: pn7v 复制这段内容后打开百度网盘手机App,操作更方便哦

  • WPF/UWP的经验
  1. Xaml的语法
  2. C#
  3. 最好了解MVVM模式或者ReactiveUI

Code

  • 创建一个AvaloniaUI的项目

了解WPF/UWP通知模式的童鞋可以使用MVVM

  • 项目结构

和WPF/UWP很相似的结构,但是不同的是Program.cs被重写了

class Program {
        // Initialization code. Don't use any Avalonia, third-party APIs or any
        // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
        // yet and stuff might break.
        public static void Main(string[] args) => BuildAvaloniaApp()
            .StartWithClassicDesktopLifetime(args);

        // Avalonia configuration, don't remove; also used by visual designer.
        public static AppBuilder BuildAvaloniaApp()
            => AppBuilder.Configure<App>()
                .UsePlatformDetect()
                .LogToDebug()
                .UseReactiveUI();
    }
  • MainWindow.Xaml

可以说和WPF/Xaml大致一模一样了,但是体验不太好地就是在Xaml标签页的智能提示和显示内容体验,以及右侧的实时渲染窗口是一帧一帧地刷新整个页面。

  • ViewModel

Avalonia UI使用地是ReactiveUI来做的界面绑定和响应。和以往使用MVVMLight不同,绑定命令不用RelayCommand,而是直接在xaml绑定一个后台的方法名。


  • 发布
    编码完成在windows上测试通过之后,就可以把程序打包发到其他平台上测试了。这里以Linux为例:
    Alt+B-->选择发布

根据目标平台选择配置保存。
点击发布,稍等片刻。。。。。。

  • 跨平台运行
    以linux为例:
  1. 将Publish的文件夹上传到Linux上
  2. 找到对应的程序名(没有任何后缀),更改权限为”允许此文件作为程序运行“
  3. 双击运行,即可看到和Windows上一模一样的效果。

问题

由于AvaloniaUI不是微软官方出品,而是民间团队开发,且目前仍处于预览。我罗列一些自己遇到问题时的解决方案

1.尝试Nuget把AvaloniaUI的包更新到最新
2.保证开发的.netcore配置比运行环境的.net core版本低

3.*字体渲染问题
这个问题是我遇到的最严重的问题,直接导致程序都不能渲染出来。如果有遇到这个问题的同学,可以首先在Program.cs下的Main函数里面加两行代码:

Console.WriteLine(SKTypeface.Default.FamilyName);
Console.WriteLine(SKTypeface.FromFamilyName("Sans").FamilyName);

然后在linux里使用控制台来运行程序,定位到程序目录,更改程序权限为可执行程序

chmod -x 程序名

运行程序

./程序名

如果出现权限不足的可以使用如下

chmod 777 程序名

如果运行程序后,控制台打印了NullRefrence的错误,那就是缺少默认字体。估计是AvaloniaUI的团队设置了程序的默认字体”Sans“。

只需要替换软件默认字体就可以了,这里我使用微软雅黑

<Application
    x:Class="AvaloniaTest.App"
    xmlns="http://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:AvaloniaTest">
    <Application.DataTemplates>
        <local:ViewLocator />
    </Application.DataTemplates>
    <Application.Resources>
        <FontFamily x:Key="yh">微软雅黑</FontFamily>
    </Application.Resources>
    <Application.Styles>
        <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml" />
        <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml" />
        <Style Selector="Window">
            <Setter Property="FontFamily" Value="{StaticResource yh}" />
        </Style>
    </Application.Styles>
</Application>

并且需要在linux安装微软雅黑的字体

sudo apt-get install ttf-mscorefonts-installer

博客园之前也有一位大佬体验AvaloniaUI时候遇到字体的问题,可是他的树莓派是可以渲染出窗体只是没有文字,但是我测试了好几个发行版本都是窗体都不渲染。大家可以参考一下他的文章树莓派 Raspberry Pi 4,.net core 3.0 ,Avalonia UI 开发

运行效果

  • 我尝试使用Face++的 API接口,测试写了一个有网络请求的抠图程序

Windows:


Linux:


其他

贴出一些参考网站给大家

  • 官网 http://avaloniaui.net/
  • GitHub http://github.com/AvaloniaUI/Avalonia
  • 树莓派使用AvaloniaUI http://www.cnblogs.com/drzhong/p/11678701.html
  • Mac使用AvaloniaUI http://www.cnblogs.com/seamas/p/11245348.html

【文章为大头BigHead原创,转载请注明出处】

本文转载于网络 如有侵权请联系删除

相关文章

  • 深夜小酌,50道经典SQL题,真香~

      晚上听说我们村子快解封了,居家办公的日子已不多,久久不能平息~~   蹲坑之余,在网上找到了50道所谓经典SQL题,这不就是深夜必备小菜?我用脚叼起拖鞋,从冰箱拿出封印已久的半瓶可乐,打开数日未见的MySQL8,来吧,来场说卷就卷的刷题。  现在是6月9号00:15分,花了近3小时撸完这小50题,有点困了,不想对所谓标准答案了。。心中有猛虎,何必细嗅蔷薇?  我先把自己的结果简单发上来(我会把题目和答案分开便与你刷题),相信和我一样爱玩儿的同学们,可以刷一遍后对照一下我的SQL,会找出我SQL中的问题,我再来复盘更新。整体来说难度中等偏低吧,但是如果你想复习SQL回味当初的你,还是比较推荐的,毕竟回味是福。废话不说了,开整。车票一、测试表数据二、50道SQL题(不含答案),用于自测三、50道SQL题(含答案),用于参考对照一、测试表数据学生表:student[学号,学生姓名,出生年月,性别] 成绩表:score[学号,课程号,成绩] 课程表:course[课程号,课程名称,教师号] 教师表:teacher[教师号,教师姓名)下面是表结构和数据,直接执行即可~------------

  • JSON 基本使用

    1.JSON是什么?JSON,全称是JavaScriptObjectNotation,即JavaScript对象标记法。JSON是一种轻量级(Light-Meight)、基于文本的(Text-Based)、可读的(Human-Readable)格式。JSON的名称中虽然带有JavaScript,但这是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript语言。JSON无论对于人,还是对于机器来说,都是十分便于阅读和书写的,而且相比XML(另一种常见的数据交换格式),文件更小,因此迅速成为网络上十分流行的交换格式。近年来JavaScript已经成为浏览器上事实上的标准语言,JavaScript的风靡,与JSON的流行也有密切的关系。因为JSON本身就是参考JavaScript对象的规则定义的,其语法与JavaScript定义对象的语法几乎完全相同。JSON格式的创始人声称此格式永远不升级,这就表示这种格式具有长时间的稳定性,10年前写的文件,10年后也能用,没有任何兼容性问题。2.JSON的语法规则是怎样的?JSON的语法规则十分简单,可称得上“优雅完美”,总

  • 安装 Docker 环境

    安装Docker环境Docker简介Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker的理念是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后个标准化组件是用户的app)。安装Docker运行时用户权限安装Docker需要sudo或root权限,推荐使用sudo,如果你的账户没有权限,请使用下面的命令来添加:sudousermod-a-Gsudo$USER复制使用Docker官方源安装1、设置DockerCE仓库在Ubuntu系统上设置DockerCE仓库。使用lsb_release-cs命令打印你的Ubuntu版本的名字,比如:xenial或者trusty。sudoap

  • 硬币找零问题

    硬币找零问题是一种经典的背包问题。顾名思义,就是你去商店买完东西,售货员会给你用若干枚硬币找钱,如何使用这些硬币完成找零。问题一:组成当前值所需最少的硬币数目给定不同面额的硬币coins和一个总金额amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1。示例1: 输入:coins=[1,2,5],amount=11 输出:3 解释:11=5+5+1 示例2: 输入:coins=[2],amount=3 输出:-1 说明: 你可以认为每种硬币的数量是无限的。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/coin-change 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。复制该问题的一个简化版,当一个大面值的硬币总是可以由小面值的硬币组合而成时(即参考软妹币),可以使用一种贪心策略即优先使用大面值的直到不能使用再使用小面值的,如此的到的即为最少硬币花费数目。解决方案使用完全背包求解。将不同面额的硬币抽象为成不同的物品,面额为物品的重量,a

  • JavaScript设计模式之迭代器模式

    Contents1介绍2实例3UML类图4代码演示5场景5.1ES6Iterator6ES6Iterator与Generator6.1代码介绍顺序访问一个集合(有序的:Array)使用者无需知道集合的内部结构实例使用jQ演示<p>jqeach</p> <p>jqeach</p> <p>jqeach</p>复制vararr=[1,2,3] varnodeList=document.getElementsByTagName('p') var$p=$('p') arr.forEach(function(item){ console.log(item); }) vari,length=nodeList.length for(i=0;i<length;i++){ console.log(nodeList[i]); } $p.each(function(key,p){ console.log(key,p) })复制上述的实例中,如果想遍历arr,a标签需要三种方式。这里定义一

  • JupyterLab: 神器Jupyter Notebook的进化版,结合传统编辑器优势,体验更完美

    01前言作者:ReneDraschwandtner编译:HuangweiAI近年来,JupyterNotebook作为一种以交互和良好的布局方式显示代码和结果的工具受到了广泛的关注。它当然有助于降低编程的门槛,并有助于教学,因为输入和处理后的输出一起在浏览器中即时呈现,这是许多用户都非常熟悉的。尽管JupyterNotebook很受欢迎,但需要编写的代码越多,经典的PythonIDE或文本编辑器就越显得方便。如果能有一种工具,能够取其精华,从而将两个优势结合在一起,那不是很好吗?JupyterLab正在努力实现这一目标,使用户能够以灵活、集成和可扩展的方式进行编程。02进化方向Jupyternotebook到JupyterLab的进化方向是基于2015年的用户体验调查,该调查强调了三个成功因素:用户喜欢笔记本的体验。用户希望组合和重新混合不同的Jupyter组分。用户需要轻松协作的能力。根据我使用Jupyternotebook的经验,分析了它的优劣势优势:Jupyternotebook在可视化功能方面特别强大。Jupyternotebook与绘图的交互非常方便,例如只需使用%matpl

  • Android开发笔记(一百四十三)任务调度JobScheduler

    任务调度 App除了通过屏幕向用户展示可交互的界面元素之外,还经常需要在后台做些背地里做的事情,比如说精密计算、文件下载、统计分析、数据导入、状态监控等等,这些用户看不到的事一般放在Service中处理。 然而有时候我们希望在特定情况下再启动事务,比如说延迟若干时间之后,或者等手机空闲了再运行,这样一方面不会在系统资源紧张之时喧宾夺主,另一方面也起到削峰填谷提高系统效率的作用。对于这些额外的条件要求,Service并不能直接支持,往往需要加入其他手段,才能较好地满足相关的运行条件,比如: 一、对于延迟时间执行,通常考虑利用系统的闹钟管理器AlarmManager进行定时管理,有关AlarmManager的说明参见《Android开发笔记(五十)定时器AlarmManager》。 二、对于是否联网、是否充电、是否空闲,一般要监听系统的相应广播,常见的系统广播说明如下: 1、网络状态变化需要监听系统广播android.net.conn.CONNECTIVITY_CHANGE; 2、设备是否充电需要监听系统广播Intent.ACTION_POWER_CONNECTED也就是android.

  • 电商网站秒杀与抢购的系统架构

    一、大规模并发带来的挑战在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常状态。我们现在一起来讨论下,优化的思路和方法哈。1.请求接口的合理设计一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。2.高并发的挑战:一定要“快”我们通常衡量一个Web系统的吞吐率的指标是QPS(Q

  • 数据结构学习笔记——树(上)

    树的定义之前一直介绍的是一对一的线性结构,可现实中还有多一对多的情况需要处理,这就是今天要介绍的一对多的数据结构——树。树(Tree):是n(n>=0)个结点的有限集。n=0时称为空树。在任意一棵非空树中:有且仅有一个特定的称为根(Root)的结点;当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、···、Tm,其中每一个集合本身又是一颗树,并且称为根的子树(SubTree),如图: 树的定义其实就是我们在说栈的时候提到的递归的方法。也就是在树的定义之中还用到了树的概念,这是一种比较新的定义方法。下图的子树T1和子树T2就是根结点A的子树。当然,D、G、H、I组成的树又是B为根结点的子树,E、J组成的树是以C为根结点的子树。 对于树的定义还需要强调两点:n>0时根结点是唯一的,不可能存在多个根结点,别和现实中的大树混在一起,现实中的树有很多根须,那是真实的树,数据结构中的树只有一个根结点。m>0时,子树的个数是没有限制的,但它们一定是互不相交的,像下图中的两个结构就不符合树的定义,因为它们有相交的子树:1、结点的分类树的结点包含一个数据

  • CountVectorizer

    CountVectorizer关于文本特征提取,前面一篇文章TF-IDF介绍了HashingTF,本文将再介绍一种SparkMLlib的APICountVectorizer。CountVectorizer和CountVectorizerModel旨在帮助将文本文档集合转化为频数向量。当先验词典不可用时,CountVectorizer可以用作Estimator提取词汇表,并生成一个CountVectorizerModel。该模型会基于该字典为文档生成稀疏矩阵,该稀疏矩阵可以传给其它算法,比如LDA,去做一些处理。在拟合过程中,CountVectorizer会从整个文档集合中进行词频统计并排序后的前vocabSize个单词。一个可选参数minDF也会影响拟合过程,方法是指定词汇必须出现的文档的最小数量(或小于1.0)。另一个可选的二进制切换参数控制输出向量。如果设置为true,则所有非零计数都设置为1.这对于模拟二进制计数而不是整数计数的离散概率模型特别有用。举例说明该算法假如我们有个DataFrame有两列:id和texts。idtexts0Array("a",&qu

  • 关于 Math.random()生成指定范围内的随机数的公式推导

    关于Math.random()生成指定范围内的随机数的公式推导 在java中,用于生成随机数的Math方法random()只能生成0-1之间的随机数,而对于生成指定区间,例如a-b之间的随机数,却只能用相关计算公式。 这个计算公式大家所熟知: intnum=(int)(a+Math.ransom()*(b-a+1)); 复制 对于这个公式,想必使用过的一定不会陌生,但是,时至今日,相信还有许多小伙伴对这个公式处于只会用,而不知其从何而来的境界。 这个公式设计的数学知识甚少,只是里面绕了一个弯,便把大部分人给绕晕了,希望这篇短小而又精悍的文章能够给大家带来些许帮助。 言归正传,首先,我们例如要求[a,b]之间的随机整数。 而Math的random方法只能生成(0,1)之间的随机数,这时,我们给Math.random()生成的随机数乘上一个b,也就是变成了公式 Math.random()*b 复制 也就是(0,1)*b,这时,能生成的随机数范围变成了(0,b)(tips:因为0*b=0,1*b=b),这时,我们要求的范围已经求出了他的最大范围值,但是,最先范围由于乘法还是零,所以,我们在再

  • 【转载】Python进阶之“属性(property)”详解

    转载 Python进阶之“属性(property)”详解     Python中有一个被称为属性函数(property)的小概念,它可以做一些有用的事情。在这篇文章中,我们将看到如何能做以下几点: 将类方法转换为只读属性 重新实现一个属性的setter和getter方法 在本文中,您将学习如何以几种不同的方式来使用内置的属性函数。希望读到文章的末尾时,你能看到它是多么有用。 开始 使用属性函数的最简单的方法之一是将它作为一个方法的装饰器来使用。这可以让你将一个类方法转变成一个类属性。当我需要做某些值的合并时,我发现这很有用。其他想要获取它作为方法使用的人,发现在写转换函数时它很有用。让我们来看一个简单的例子: classPerson(object): """""" def__init__(self,first_name,last_name): """Constructor""" self.first_name=first_name self.last_name=last_name @property deffull_name(self):

  • j-dict-text样式修改

    j-dict-text样式修改 主要是用到了动态class,详情见https://cn.vuejs.org/v2/guide/class-and-style.html 注:修改样式时要注意权重问题,否则修改的样式不生效 增加权重样式穿透,::v-deep等同于/deep/,等同于>>>

  • 今天廷鹏师弟来的java建议

    如下一段获取数据代码的问题:  publicSerializablegetById(Serializableid)throwsBaseBusinessException{  if(id==null)   thrownewBaseBusinessException("根据给出的Id获得对象时,ID不得为空!");  try{   returnbasicDAO.findById(id);   }catch(BaseDBExceptione){   log.error("根据给出的Id获得对象:"+getObjectName()+"失败");   e.printStackTrace();   thrownewBaseBusinessException(e.getMessage());   //}  } } 问题: &

  • python-questions

    1.__sizeof__与len的区别 >>>a=range(3) >>>a.__sizeof__() 24 >>>len(a) 3>>>a.__sizeof__.__doc__'__sizeof__()->int\nsizeofobjectinmemory,inbytes'复制

  • bzoj 2039: [2009国家集训队]employ人员雇佣【最小割】

    一开始在https://www.cnblogs.com/lokiii/p/10770919.html基础上连(i,j,b[i][j])建了个极丑的图T掉了……把dinic换成isap勉强能卡过 首先因为有正负收益所以考虑最小割,先ans=Σb,然后考虑负收益 把割完后和s相邻的视为不选,反之视为选,选的话要付出代价a,所以连(s,i,a[i]);然后考虑如果ij一个选一个不选(这里是单向的),需要Eij的代价,所以连(i,j,E[i][j]);然后是如果一个点不选的话那么所有Eij都不会被加,所以连边(i,t,ΣE[i][j]) 跑最小割即可 #include<iostream> #include<cstdio> #include<queue> #include<cstring> usingnamespacestd; constintN=1005; intn,s,t,h[N],cnt=1,le[N]; longlongb[N][N],ans; structqwe { intne,to; longlongva; }e[N*N*4]; int

  • 双连通分量

    坑,没找到模板题。 暂时先放一放。 有两种版本的,不知道那个比较好。 http://blog.csdn.net/u013497977/article/details/47188489 http://blog.csdn.net/fuyukai/article/details/51303292

  • php Array

    1.创建数组 创建一个包含指定范围的数组  arrayrange(mixedlow,mixedhigh[,numberstep]); 基于变量创建一个数组  arraycompact(mixedvarname[,mixed…]);    extract(array&array)将数组解析为变量 2.计算数组大小  count() sizeof()   3.遍历数组 each()函数返回数组当前键值并将数组指针向前移动一步。array each(array&array);   list语言结构,将数组中的值赋给一些变量。  list(mixedvarname,mixedvarname…) 4.添加与删除一个数组元素 1array_unshift()用于在数组开头插入一个或多个元素。 array_unshift(array&array,mixedvar[,mixedvar…]); array_shift(array&array) 2array_push()用于

  • JAVA框架-MVC模式

    MVC MVC模式代表Model-View-Controller(模型-视图-控制器)模式。这种模式用于应用程序的分层开发。 Model(模型)-模型代表一个存取数据的对象或JAVAPOJO。它也可以带有逻辑,在数据变化时更新控制器。 View(视图)-视图代表模型包含的数据的可视化。 Controller(控制器)-控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。 案例 下面我们来写一个简单的登录的案例,来提现MVC的设计模式 首先,我们有一个数据库,里面存放用户信息如下: OK,下一步我们建立一个简单的登录界面前端的页面如下: <%@pagecontentType="text/html;charset=UTF-8"language="java"%> <html> <head> <title>登录界面</title> </head> <body> <spanstyle="color:#ff4a4f">${requestScope.er

  • 学习网站-不定期更新

    Linux学习 基础部分 http://linuxtools-rst.readthedocs.io/zh_CN/latest/base/index.html 这一部分主要介绍Linux常用命令工具,比如文件管理、文本处理;为了让读者用最少的时间掌握到常用的知识,对于每个工具的举例,尽量做到小而精; 注解:本书并非一本讲解Linux各种命令的完整用法的书,并且假设读者已经熟悉Linux命令行下的基本操作。如果读者对Linux操作系统尚不了解,可以参考《鸟哥的私房菜基础学习篇》一书。   ubuntu的入门教程 http://wiki.ubuntu.org.cn/%E6%96%B0%E6%89%8B%E5%85%A5%E9%97%A8%E6%8C%87%E5%BC%95   鸟哥的私房菜网址 http://linux.vbird.org/linux_basic_train/   这个翻译也不错的,简单基础并且快速上手 http://billie66.github.io/TLCL/book/index.html  

  • C# 通过反射获取类属性标识名称

    JSON序列化的时候,往往前后端的属性名称回不一样,尤其是再调用第三方接口的时候,为了减少这方便的麻烦,一般我们在自定义实体的时候,回使用数据契约(DataContract)  一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送,如下所示。 [DataContract(Name="People")] publicclassPerson { [DataMember(Name="Name")] publicStringUserName{get;set;} [DataMember(Name="Age")] publicStringUserAge{get;set;} }复制 DataMember(数据成员)有很多属性,这里不一一讨论,主要说一下如何通过属性名获取DataMember的Name属性 一、获取类所有属性的标记名称 ///<summary> ///获取属性标记名称 ///</summary> ///<returns></returns> publicList<Strin

相关推荐

推荐阅读