V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
freewing999
V2EX  ›  程序员

.NET 各运行时代码统一的技巧- IDonetPlatform

  •  1
     
  •   freewing999 · 2015-10-26 16:24:32 +08:00 · 2806 次点击
    这是一个创建于 3295 天前的主题,其中的信息可能已经有所发展或是发生改变。

    哪里都缺程序员

    “老王,我这里钱有了,产品概念有了,就差一个程序员了,你 iOS , android , Windows 你都会么?”

    “我……额,喂!信号不好,我这里听不见……”
    “嘟……”

    其实,很多产品初创的时候,做一个应用不必考虑一定要追求极致的性能,都奔着 Native Code 去做,大火大热的 React Native 风生水起,其实 Cross Platform 可以作为一个初创团队人手不足的情况下应该考虑采用这种跨平台的去实现自己的产品的前几个迭代版本,毕竟人是活的,代码是死的。

    Xamarin ,这不是个广告

    因为笔者本身是 .NET 出身,也关注 Xamarin 很久了,自从微软把他收编之后我发现其实,一套代码做出 iOS , Android , Windows ( WinForm & WPF ), Windows Phone 这件事情在实现上成为可能。

    不过随着开发的深入,你会发现,坑还是有,并且很深。诸多 Xamarin 的教程我就不列举了。我只是来简述一下如何踩坑。

    最简单的一个需求:我要在各个平台上实现一个微信的聊天服务,服务端已经有了使用 WebSocket 现成的服务,而客户端需要有一个 WebSocket 客户端去实现收发数据,那么如何用高度一致的代码在

    • Xamarin iOS
    • Xamarin Andoid
    • Windows PC
    • Windows Phone

    实现这样的需求呢?

    老思路解决新问题

    面对对象的小蛮腰就是多态,迷人的变化。
    在刚才列举的四个运行时下,除了 Windows PC 下有微软官方实现的一个WebSocket for Windows PC runtime,其余的都没有官方给出实现,因此我们会想到,在 Windows Phone | Xamarin Andoid | Xamarin Andoid 分别采用第三方库来解决这个问题,现在问题来了,本来我的想法是一套代码解决这些问题,可是一旦引入了第三方库,接口就会不一样,我就要针对每一个平台单独去编写收发消息的方法,例如下面这种是很多程序员经常使用的方式:

    #if Xamarin_Andoid || Xamarin_iOS|| Windows_Phone
    #endif
    
    #if Windows_PC
    #endif
    

    这种方式实现多平台共享代码是很痛苦的,并且这种实现方式的上下逻辑得非常高明,这个对程序员的脑子烧的很痛。

    接口的引入——开始「变态」 了

    因此,我们需要封装掉变化,引入一个接口,让每个平台的底层实现向上透明,我只告诉你我的接口可以实现收发消息,至于我底层采用什么库,用什么框架你别管。

    public interface IWebSocket
        {
            /// <summary>
            /// 初始化 WebSocket 连接
            /// </summary>
            /// <param name="server">服务器地址.</param>
            /// <returns>返回的是一对值,状态码和具体的返回值</returns>
            Task<Tuple<int, string>> InitWebSocket(string server);
    
            /// <summary>
            /// 异步发送(基于 Task 的编程已经是 .NET 的主流了.)
            /// </summary>
            /// <param name="data">The data.</param>
            /// <returns>int 表示状态码,参考 HTTP StatusCode 设计的,而 String 可能是服务器告诉你这条消息发送之后的一些参数,比如收到的具体时间,等等都编码之后封装在 String 里面,客户端自行解析</returns>
            Task<Tuple<int, string>> SendAsync(string data);
    
            /// <summary>
            /// 定义收到消息之后激发的事件,这是聊天应用常用的被动通知
            /// </summary>
            event EventHandler<string> OnReceived;
    
            /// <summary>
            /// 当前连接的状态,可能断线了,可能尚未初始化.
            /// 这个枚举其实每个库都会有自己定义的类型,但是我依然在我自己的应用中定义了符合自己需求的
            /// </summary>
            /// <value>
            /// 连接状态
            /// </value>
            SocketStatus status { get; set; }
        }
        public enum SocketStatus
        {
            None,
            SocketConnected,//socket opend.
            SocketDisconnected,//socket closed.
        }
    

    然后呢,每一个项目里面单独实现这个接口:

    namespace MyProject.RealtimeMessage
     {
    
     public class MyWebSocket : IWebSocket{
     // 接口实现的一些代码
     }
    
     }
    

    这里有一个必须声明的地方,这个实现的接口的类的名字必须一致(每个项目都有这个类,都叫 MyWebSocket)。

    然后在真正初始化的时候,我们需要如下代码在运行时把他召唤出来:

    Type webSocketType = Type.GetType("MyProject.RealtimeMessage.MyWebSocket");
    
     IWebSocket webSocket = Activator.CreateInstance(webSocketType) as IWebSocket;
    

    这样每一个平台使用 IWebSocket 这个接口的功能去具体实现自己收发消息的功能,而且逻辑代码是每个项目(csproj)都可以共用的(用快捷方式引入代码这个技巧不用我说吧……)

    以上只是抽象了我从真实项目里面实践的经验简单的描述了一下。

    至此。

    20 条回复    2015-10-28 23:04:45 +08:00
    longaiwp
        1
    longaiwp  
       2015-10-26 16:37:51 +08:00
    嗯,其实很多项目都是这样做的,这个可以参照 Github 上面的一些开源代码
    br00k
        2
    br00k  
       2015-10-26 16:57:05 +08:00
    这货貌似还挺贵的吧。。没见什么人用。。。
    laball
        3
    laball  
       2015-10-26 18:31:55 +08:00
    小弟使用过一段时间,有一些体会:
    1 、太贵,社区已经有人发帖公开批评了;
    2 、绑定第三方库台折腾,比起原生的 Java 开发,成本上升,竞争力下降;
    3 、国内用的公司还是太少,资料也少,没有形成规模的社区,有问题,找不到地方问;
    freewing999
        4
    freewing999  
    OP
       2015-10-26 19:39:44 +08:00
    @longaiwp 恩,关键是有时候封装的接口设计是一门很深的学问,一不小心就容易造成各个平台的坑,关键是看具体牵扯到底层数据交互的协议, socket , http 这些通用的都还好,不常用的,甚至是私有的,数据交互都得自己写的时候,那 .NET 跨平台的坑就太多了。。。
    freewing999
        5
    freewing999  
    OP
       2015-10-26 19:42:14 +08:00
    @br00k 我也就用免费版的不停的切换邮箱账号,神经病买才会买这么贵的 IDE ……还没创造出价值就提前问初创团队要钱,其实应该像 Unreal 一样,你盈利了我就要你的钱,你不盈利,但是你用了我的产品,提高了我产品的使用率,那也是双赢的。 Xamarin 的决策层还活在 2010 年之前的世界里。
    dqh3000
        6
    dqh3000  
       2015-10-26 20:20:48 +08:00
    哈哈,好想吐槽要跨平台用.net 真的好吗

    想起今天早上微博看到微软发布用小米

    安利 HTML5 ,我们能开发微信端哦,你们别人能吗,呵呵
    longaiwp
        7
    longaiwp  
       2015-10-26 21:00:11 +08:00
    @freewing999 说句法律不正确和道德不正确的:你可以用盗版
    dcoder
        8
    dcoder  
       2015-10-26 23:08:22 +08:00
    @freewing999
    Xamarin 生态系统太差,而且本身变数也大,即使被 MS 收编了.

    我说个更好的思路,你 C#出身,想做跨平台 app ,应该直接上 Unity.
    以 Unity 现在强大的生态系统,做跨平台 app, 完全没有问题.

    responsive UI 素材
    https://www.assetstore.unity3d.com/en/#!/content/29757

    能缩放的高级字体
    https://www.assetstore.unity3d.com/en/#!/content/17662

    Web View
    https://www.assetstore.unity3d.com/en/#!/content/32461

    iOS 和 Android 的 native features, 如果你需要的话
    https://www.assetstore.unity3d.com/en/#!/content/7421
    https://www.assetstore.unity3d.com/en/#!/content/10825
    zongwan
        9
    zongwan  
       2015-10-27 10:06:57 +08:00
    随口说说之前看到的笑话
    新的 window phone OS 出了 微软宣布自家的 Xamarin 不支持此 OS
    还好 Xamarin 社区之后给出了支持版本...

    这个笑话之前距离微软卖诺基亚队友的笑话没多久
    freewing999
        10
    freewing999  
    OP
       2015-10-27 10:17:40 +08:00
    @dcoder 鄙人也是 Unity 的一个小小的开发,不过专注于底层数据逻辑,我文中所列举的方法在 Unity 也是可行的(因为我这么干过), Unity 的 Mono 版本还没有跟上,况且它是个专业的游戏引擎,不适合做 App 。做 App 还是考虑初期用 cross platform ( React | Xamarin |),融资成功之后再考虑采用 Native Code ,对于一个技术出身又想圈钱的团队来说,先实现基础的功能,把应用做出来,有货才能唬住投资人, Android ( Java )& iOS ( Object-C ) 都很好学,等到团队资金充足考虑后期做高精尖的需求,性能优化要上纲上线的时候,复刻自己的产品,根本没难度。
    freewing999
        11
    freewing999  
    OP
       2015-10-27 10:24:39 +08:00
    @zongwan 哈哈哈哈哈哈(先声明:本人是 ex WP developer ),微软自己的手机系统( Windows Phone )确实不合众,也不算好用,很多系统级别的设计是自成一套但是无法迎合普通消费者口味,悲观地认为,这系统不会死,但是一直会是 1%(包括即将「大面积」上市的 Winodws 10 for Mobile )。
    dcoder
        12
    dcoder  
       2015-10-27 10:45:24 +08:00
    @freewing999
    何谓 "Unity 的 Mono 版本" ?
    直接用 Unity + Unity 生态中无数高质量的 assets, 就可以做跨平台 app 了.
    我不觉得 "专业的游戏引擎,不适合做 App".
    React 这种看着还不错,不过还是太新,生态系统没成长起来呢.

    另外,在 Unity 里用 websocket, 跨平台使用,不是直接有现成的?
    https://www.assetstore.unity3d.com/en/#!/content/10872
    freewing999
        13
    freewing999  
    OP
       2015-10-27 11:16:12 +08:00
    @dcoder 哥,你用 Unity 没发现它支持 .NET 语言去编写游戏逻辑么? Unity 也采用的是 Mono 来支持 .NET 语言的。。。而 Mono 的亲爹就是 Xamarin ……况且你贴给我的那个收费组件我早就研究过了,它也是用 CSharp 语言写的。。。我文章是演示,如何通过一套代码支持 Xamarin iOS, Xamarin Andorid , Windows PC , Windows Phone 甚至是 Unity (因为 Unity 本身就采用了 Xamarin 的亲儿子 )……
    dcoder
        14
    dcoder  
       2015-10-27 13:15:01 +08:00
    @freewing999
    误会了,我当然知道 Unity 和 Mono 的关系,看懂了你之前说的意思: Unity 的 Mono/.NET 版本不够新.
    dcoder
        15
    dcoder  
       2015-10-27 13:28:22 +08:00
    @freewing999
    难得遇上个写 Xamarin ,顺便请教下 :)
    如果我就写些带 2D GUI 的 app ,用 Xamarin 跟用 Unity 到底有什么优势?

    自己用 Unity 一段时间了,觉得 Unity 和其生态很强,比如写个 2D 游戏就比用 Cocos2D 之类方便太多.
    Unity 4.6 后新的 uGUI 和一些衍生的 assets 也非常好用,我觉得用来做些带 2D GUI 的 app 也非常方便. 就做非 3D app 的话, Xamarin 到底哪些方面能比 Unity 好用呢?
    freewing999
        16
    freewing999  
    OP
       2015-10-27 14:48:42 +08:00
    @dcoder 回到原始的话题, Unity 是游戏引擎,做游戏专业,做数据交互是弱势, Assets Store 里面的东西大部分都是为游戏定制的,而且好用的都是收费的, Xamarin 的专业是做应用,例如社交,数据展现等等, Xamarin 最大的优势就是它自带的跨平台的 Mono 运行时几乎是最新的,可以享受几乎跟原生 C# 一样的各种新技术, Unity 碍于版权以及自身业务场景的专一,不适合做类似「微信」「微博」这样的应应用。各司其职是最好的。总结一下: Xamarin 的 Mono 比 Unity 的 Mono 好用的不只一点点。换个角度,如果你是做移动游戏的,请一定选择 Unity 。应用 跟 游戏 始终还是 2 个领域。
    hjkl0001
        17
    hjkl0001  
       2015-10-27 15:43:49 +08:00
    Unity 研究研究。。。
    dcoder
        18
    dcoder  
       2015-10-28 00:10:36 +08:00
    @freewing999
    那你的主要观点还是 Xamarin 的 Mono/.NET 版本新给开发一般 app 带来很多好处? 能给几个例子么?
    freewing999
        19
    freewing999  
    OP
       2015-10-28 09:11:52 +08:00
    @dcoder
    1. 几乎最新的 .NET 版本。
    2. 一个虽然有点贵,但是做一般 APP 开发都较为友好的 IDE 。
    3.在 Nuget 上原生的 .NET 可以引用的 lib 在 Xamarin 下依然可以使用。

    不要再纠缠了这个问题了, Unity 是个游戏引擎,不是做微信,微博这种应用的,我也不是说 Xamarin 一定是跨平台的唯一选择,只是建议 .NET 出身的工程师可以考虑做「应用」的时候选择 Xamarin ,而做 JavaScript 出身的工程师必然可以考虑 React Native ,只是我不理解为什么你总纠缠于 Unity 这种游戏引擎来做应用,换言之,你是否真用 Unity 实现过类似于微信对话列表这种对于一般应用开发框架来说最简单的 List 展现的东西,用 Unity 做应用 ,我只能比喻为:为了吃个红烧鸡翅,犯得着用洲际导弹去杀鸡么。。。
    dcoder
        20
    dcoder  
       2015-10-28 23:04:45 +08:00
    @freewing999
    对话列表 list 展示, 这种简单的 GUI 功能, 对于 Unity 来说容易做.
    不过,让没有 3D 背景的同事,学用 Unity 确实麻烦.
    你列出的 1 3 点,倒是值得考虑,如果是 .NET 熟手,估计有不少自己用熟了的功能和 lib 放不下.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1067 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 454ms · UTC 19:37 · PVG 03:37 · LAX 12:37 · JFK 15:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.