“老壇泡新菜”:SOD MVVM框架,讓WinForms煥發新春

来源:http://www.cnblogs.com/bluedoctor/archive/2016/11/13/6060278.html
-Advertisement-
Play Games

Web前端技術的發展使得MVVM模式相比WPF時代更加流行,然而老舊的WinForms仍然占據桌面開發技術很大一部分,現在SOD框架提供了WinForms MVVM支持,老壇泡新菜,讓WinForms煥發新春。 ...


火熱的MVVM框架

最近幾年最熱門的技術之一就是前端技術了,各種前端框架,前端標準和前端設計風格層出不窮,而在眾多前端框架中具有MVC,MVVM功能的框架成為耀眼新星,比如GitHub關註度很高的Vue.js ,由於是國人作品,其設計風格和文檔友好度對國人而言更勝一籌,因此我也將它推薦到公司採用,其中我推薦都理由就是它非常優秀的MVVM功能,面向數據而不是面向DOM細節相比jQuery等更加節省代碼,更符合後端程式員的胃口,也更有利於UI設計人員跟程式員都分工配合。

下麵是Vue.js實現MVVM功能的原理圖:

                       

 

前面說的Vue.js框架這些優點的是否很眼熟?沒錯,這就是早些年流行於WPF的MVVM技術,相比WinForms技術,WPF可以提供給UI設計人員更加強大的設計能力,做出更炫更好看的界面。只不過MS的很多技術總是很超前技術更新很快,WPF新推出的時候WinForms還占據桌面開發主要領域,隨後還沒有火起來移動開發時代已經來臨,基於Web的前端技術大大發展,從而風頭蓋過了WPF,但是WPF引入的MVVM思想卻在Web前端得到了發揚光大,現在各種基於MVVM的前端框架猶如雨後春筍。

WinForms上的MVVM需求

Web前端技術的大力發展,各種跨平臺的基於HTML5的移動前端開發技術逐漸成熟,各種應用逐步由傳統的C/S 轉換到 B/S ,APP模式,基於C/S模式的前端技術比如WPF的關註度逐漸下降,因此WPF上的MVVM並不是應用得很廣,目前很多遺留的或者新的 C/S系統仍然採用WinForms技術開發維護,然而WinForms 上卻沒有良好的MVVM框架,WinForms 的UI效果和整體開發質量,開發效率沒有得到有效提高,要過度到WPF開發這種不同開發風格的技術難度又比較大,所以,如果有一種能夠在 WinForms 上的MVVM框架,無疑是廣大後端.NET程式員的福音。

 

筆者一直是一個奮鬥在一線的.NET開發人員,架構師,對於Web 和桌面,後端開發技術都有廣泛的涉及,深刻理解開發人員自嘲自己為“碼農”的心理的,工作辛苦又沒有時間陪女朋友陪家人,所以我一直總結整理如何提高開發效率,改善開發質量的方法,經過近10年的時間,發展完善了一套開發框架—SOD框架。最近研究改善Web前端開發的技術,Vue.js框架的MVVM思想再一次讓我覺得WinForms上MVVM技術的必要性,發現要實現MVVM框架其實並不難,關鍵在於模型(Model)和視圖(View)的雙向綁定,即模型的改變引起視圖內容的改變,而視圖的改變也能夠引起模型的改變。

 

SOD WinForms MVVM實現原理

要實現這種改變,對於被綁定方,必須具有屬性改變通知功能,當綁定方改變的時候,通知被綁定方讓它做相應的處理。在.NET中,實現這種通知功能的介面就是:

 INotifyPropertyChanged

它的定義在System.dll 中,早在 .NET 2.0 就已經支持。下麵是該介面的具體定義:

namespace System.ComponentModel
{
    // 摘要: 
    //     向客戶端發出某一屬性值已更改的通知。
    public interface INotifyPropertyChanged
    {
        // 摘要: 
        //     在更改屬性值時發生。
        event PropertyChangedEventHandler PropertyChanged;
    }
}


SOD框架的實體類基類 EntityBase 實現了此介面:

public abstract class EntityBase : INotifyPropertyChanged, ICloneable, PWMIS.Common.IEntity
{
/// <summary>
        /// 屬性改變事件
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 觸發屬性改變事件
        /// </summary>
        /// <param name="propertyFieldName">屬性改變事件對象</param>
        protected virtual void OnPropertyChanged(string propertyFieldName)
        {
            if (this.PropertyChanged != null)
            {
                string currPropName = EntityFieldsCache.Item(this.GetType()).GetPropertyName(propertyFieldName);
                this.PropertyChanged(this, new PropertyChangedEventArgs(currPropName));
            }
       }
// 其它代碼略… … 
  }

所以SOD框架的實體類可以直接用來作為MVVM上的Model提供給View 做為被綁定對象,因此要我們只需要解決WinForms 形式的View 元素如何實現綁定操作,那麼我們的WinForms 應用即可實現MVVM功能了。在WinForms 上,控制項基本上都已經實現了綁定功能,它就是控制項的 DataBindings,向它添加綁定即可,例如下麵的例子:

 

this.textbox1.DataBindings.Add("Text", userEntity, "Name");

這樣當文本框架輸入的內容改變後,實體類對象 userEntity.Name 屬性的值也會改變。如果userEntity是SOD實體類,所以userEntity.Name 改變,文本框的Text屬性也會同步改變。

 

SOD框架的數據控制項(WinForms,WebForms)都實現了 IDataControl 介面,它定義了幾個重要的屬性 LinkObject,LinkProperty :

/// <summary>
    /// 數據映射控制項介面
    /// </summary>
    public interface IDataControl
    {
        
        /// <summary>
        /// 與資料庫數據項相關聯的數據
        /// </summary>
        string LinkProperty
        {
            get;
            set;
        }
        
        /// <summary>
        /// 與數據關聯的表名
        /// </summary>
        string LinkObject
        {
            get;
            set;
        }
// 其它介面方法內容略… … 

我們可以使用 LinkObject 來指定要綁定的實體類對象,而LinkProperty 來指定要綁定的對象的屬性,因此可以通過下麵的代碼實現WinForms 控制項與SOD實體類的雙向綁定:

 

public void BindDataControls(Control.ControlCollection controls)
        {
            var dataControls = MyWinForm.GetIBControls(controls);
            foreach (IDataControl control in dataControls)
            {
                //control.LinkObject 這裡都是 "DataContext"
                object dataSource = GetInstanceByMemberName(control.LinkObject);
                if (control is TextBox)
                {
                    ((TextBox)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
                }
                if (control is Label)
                {
                    ((Label)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
                }
                if (control is ListBox)
                {
                    ((ListBox)control).DataBindings.Add("SelectedValue", dataSource, control.LinkProperty, false, DataSourceUpdateMode.OnPropertyChanged);
                }
            }
        }

 

另外,我們可能還需要將 一些命令綁定到視圖上,而要實現此功能也比較簡單:

private Dictionary<object, CommandMethod> dictCommand;
public delegate void CommandMethod();

        public void BindCommandControls(Control control,CommandMethod command)
        {
            if (control is Button)
            {
                dictCommand.Add(control, command);
                ((Button)control).Click += (sender, e) => {
                    dictCommand[sender](); 
                };
            }
        }

經過這樣的過程後,我們僅需要在窗體載入事件上寫下麵的幾行代碼就行了:

SubmitedUsersViewModel DataContext{get;set;}

       private void Form1_Load(object sender, EventArgs e)
        {
            base.BindDataControls(this.Controls);
            base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);
            base.BindCommandControls(this.button2, DataContext.UpdateUser);
            base.BindCommandControls(this.button3, DataContext.RemoveUser);
        }

上面的代碼中,首先定義了一個視圖模型對象 DataContext,在方法 BindDataControls 裡面作為綁定到視圖控制項上的對象,它裡面的 CurrentUser屬性的Name屬性綁定到了文本框控制項上,所以 CurrentUser.Name 是作為複合屬性來綁定的,對於標簽控制項和列表框控制項,也是類似的過程,如下圖:

 

這樣,在視圖上做簡單的數據屬性設置和寫少量的code behind綁定代碼,一個具有雙向綁定功能的程式就好了。

 

MVVM示例解決方案

解決方案概覽

為了向大家演示SOD框架對於MVVM的支持,我們搭建一個簡單的解決方案,一共分為三個項目程式集,分別對應MVVM的三大部分:

WinFormMvvm:            WinForm 示常式序主程式,視圖類所在程式集

WinFormMvvm.Model:      模型類程式集

WinFormMvvm.ViewModel:  視圖模型程式集

 

搭建好的解決方案圖如下:

 

註意:此解決方案是使用SOD Ver 5.5.5.1019 做的,因為這是目前nuget 上SOD的版本,最新的SOD框架已經把WinFormMvvm項目的 MvvmForm.cs 文件納入到框架之內了。

 程式在App.config中指定了本次附加測試的資料庫,資料庫類型為 Access,預設的連接字元串可能要求Office 2007以上版本支持。

下麵是App.config 的內容:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name ="default" connectionString ="Provider=Microsoft.ACE.OLEDB.12.0;Jet OLEDB:Engine Type=6;Data Source=testdb.accdb" providerName="Access"/>
  </connectionStrings>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="PWMIS.Core" publicKeyToken="17ba13a12b9fd814" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.5.5.1019" newVersion="5.5.5.1019" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

如果你需要更低版本的 Access 資料庫支持,或者換用其它資料庫(比如 SqlServer),請閱讀參考下麵步驟提供的信息:

1,打開下麵鏈接:

   http://pwmis.codeplex.com/

2,看到內容章節“3,修改下App.config 文件的連接配置”;

3,點擊本節下的鏈接“2.2.3 擴展數據訪問類配置”。

 

 

創建MVVM的WinForm視圖

這是一個簡單的WinForm 窗體,有三個SOD“數據控制項”,包括:一個標簽控制項顯示用戶的ID,文本框控制項顯示用戶名,一個列表框控制項顯示已經有用戶列表,三個按鈕分別用來向列表添加,修改和刪除數據。

對於數據控制項,可以在此窗體設計器界面,打開“工具箱”,在“常規”選項卡裡面,選擇上下文菜單“選擇項”,瀏覽到packages\PDF.NET.SOD.WinForm.Extensions.5.5.5.1020\lib目錄,選擇“Pwmis.Windows.dll” ,即可看到SOD的數據控制項,然後拖拽到窗體上即可。

註意我們不會給這三個按鈕控制項直接設置單擊事件,而是通過命令綁定的形式。例如對應添加按鈕,我們如下綁定命令(視圖模型的一個方法):

base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);

這會將添加用戶的按鈕控制項的單擊事件,綁定到DataContext的SubmitCurrentUsers 方法上。

 

而對於數據控制項的綁定,只需要下麵的一行代碼:

 

base.BindDataControls(this.Controls);

 

前面已經說過,該方法會遍歷方法上第一個參數裡面的所有數據控制項,找到LinkObject和LinkProperty屬性,實現數據控制項和視圖模型對象的綁定,這裡綁定的是 DataContext對象的CurrentUser對象的屬性。

 

單擊屬性瀏覽器中數據控制項的LinkProperty 屬性旁邊的“…”按鈕,會彈出下麵的“數據控制項屬性選擇器”窗體:

 

由於這裡我們要綁定的對象是當前窗體的DataContext對象,所以需要瀏覽選擇到主程式集,這樣在屬性名稱一欄,會顯示此對象所有的屬性和子屬性。註意如果DataContext對象沒有出現在列表裡面,需要檢查Form 窗體是否聲明瞭 DataContext對象,並且需要首先編譯一次程式集。最後,單擊確定,我們就設置好了數據控制項要綁定的信息。

 

創建MVVM的模型

我們的模型很簡單,就是負責創建新用戶,載入已有用戶,添加,修改或者刪除用戶,並且這些操作都是針對資料庫的,也就是我們通常的CRUD操作。由於是示例沒有太多邏輯,我們直接看代碼即可:

public class UserModel
    {
        private static int index = 0;
        private LocalDbContext context;
        public UserModel()
        {
            context = new LocalDbContext();
        }

        public List<UserEntity> GetAllUsers()
        {
            var list= OQL.From<UserEntity>().ToList(context.CurrentDataBase);
            int max = list.Max(p => p.ID);
            index = ++max;
            return list;
        }
        public void UpdateUser(UserEntity user)
        {
            int count= context.Update<UserEntity>(user);
        }

        public void AddUsers(IList<UserEntity> users)
        {
            int count = context.AddList(users);
        }

        public void SubmitUser(UserEntity user)
        {
           int count = context.Add(user);
        }

        public void RemoveUser(UserEntity user)
        {
            int count = context.Remove(user);
        }

        public UserEntity CreateNewUser(string userName="NoName")
        {
            return new UserEntity()
            {
                 ID= ++index,
                 Name =userName
            };
        }
    }
View Code

用戶模型類會使用用戶實體類,它也很簡單,只有一個ID屬性和一個Name屬性,詳細內容如下:

public class UserEntity:EntityBase
    {
       public UserEntity()
       {
           TableName = "Tb_User";
           PrimaryKeys.Add("UserID");
       }
        public int ID {
            get { return getProperty<int>("UserID"); }
            set { setProperty("UserID", value); }
        }

        public string Name
        {
            get { return getProperty<string>("UserName"); }
            set { setProperty("UserName", value); }
        }

    }

該用戶實體類雖然很簡單,卻可以直接提供給視圖作為模型綁定的元素,因為SOD實體類都實現了“屬性修改通知”介面,前面已經詳細說明。

接下來就是操作此用戶實體類的數據上下文了,用戶模型類展示瞭如何使用它,但是它的定義卻很簡單:

    class LocalDbContext : DbContext
    {
        public LocalDbContext()
            : base("default")
        {
            //local 是連接字元串名字 
        }

        protected override bool CheckAllTableExists()
        {
            //創建用戶表 
            CheckTableExists<UserEntity>();
            return true;
        }
    }

至此,一個簡單的MVVM模型類的全部定義就完成了。

 

創建MVVM的視圖模型

視圖模型是對視圖的一個抽象,它封裝了主要的視圖處理邏輯,與MVP的Presenter不同,視圖模型並不會包含詳細視圖元素的抽象,比如一個抽象的列表控制項,而是對視圖可能用到的數據進行封裝,並且可能包含對後端MVVM的模型對象調用。

在本例中,我們的用戶視圖模型的功能也很簡單,就是提供視圖需要的用戶列表和響應視圖的增加,修改,刪除用戶的命令,詳細代碼如下

public class SubmitedUsersViewModel
    {

        private UserModel model = new UserModel();
        public BindingList<UserEntity> Users { get; private set; }
        public UserEntity CurrentUser { get; private set; }

        
        UserEntity _selectUser;
        /// <summary>
        /// 當前選擇的用戶,如果設置,則會設置當前用戶
        /// </summary>
        public UserEntity SelectedUser {
            get { return _selectUser; }
            set {
                _selectUser = value;
                this.CurrentUser.ID = value.ID;
                this.CurrentUser.Name = value.Name;
            }
        
        }

        int _selectedUserID;
        public int SelectedUserID
        {
            get { return _selectedUserID; }
            set {
                _selectedUserID = value;
                var obj = this.Users.FirstOrDefault(p=>p.ID==value);
                if (obj != null)
                {
                    this.CurrentUser.ID = obj.ID;
                    this.CurrentUser.Name = obj.Name;
                    _selectUser = this.CurrentUser;
                }
                
            }
        }

        public SubmitedUsersViewModel()
        {
            var data = model.GetAllUsers();
            Users = new BindingList<UserEntity>(data);
            CurrentUser = new UserEntity();

        }

        public void UpdateUser()
        {
            var obj = this.Users.FirstOrDefault(p => p.ID == this.CurrentUser.ID);
            if (obj != null)
            {
                obj.Name = this.CurrentUser.Name;
                //更新後必須調用 ResetBindings 方法,否則控制項上的數據會丟失一行
                this.Users.ResetBindings();

                model.UpdateUser(obj);
            }
            
        }
        public void UpdateUser(int id,string name)
        {
            var obj = this.Users.FirstOrDefault(p => p.ID == id);
            if (obj != null)
            {
                obj.Name = name;
                //更新後必須調用 ResetBindings 方法,否則控制項上的數據會丟失一行
                this.Users.ResetBindings();

                model.UpdateUser(obj);
            }
        }

        public void SubmitUsers(UserEntity user)
        {
            //UserEntity newUser = new UserEntity();
            //newUser.ID = user.ID;
            //newUser.Name = user.Name;
            //Users.Add(newUser);
            if (!Users.Contains(user))
            {
                Users.Add(user);
                model.SubmitUser(user);            
            }
        }
        public void SubmitCurrentUsers()
        {
            UserEntity newUser = model.CreateNewUser(CurrentUser.Name);
            SubmitUsers(newUser);
            CurrentUser.ID = newUser.ID;
        }

        public void RemoveUser()
        {
            if (SelectedUser == null)
            {

                return;
            }
            var obj = this.Users.FirstOrDefault(p => p.ID == SelectedUser.ID);
            if (obj != null)
            {
                this.Users.Remove(obj);
                //更新後必須調用 ResetBindings 方法,否則控制項上的數據會丟失一行
                this.Users.ResetBindings();

                model.RemoveUser(obj);
            }
        }
    }
View Code

 

添加Nuget包引用

對於整個解決方案,我們都需要添加 PDF.NET Core 包,但是對於我們的WinForms 主程式,需要額外添加2個相關的包,一個SOD WinForm擴展和一個SOD Access 擴展,下麵是解決方案安裝的全部包示意圖:

 

運行解決方案

經過上面的過程,我們添加了視圖元素,設置好了視圖元素的數據綁定,創建了模型和視圖模型對象,一個簡單的MVVM示常式序就好了,下麵是運行效果圖:

 

SOD WinForms MVVM支持

自SOD框架版本 5.6.0.1111 發佈的這個“光棍節“版本中,您已經可以在此以後的版本中獲得直接的WinForms MVVM支持,如果是之前的版本,那麼需要本示常式序一樣稍微多做一點工作,但這對於你現有的SOD支持的解決方案來說不會造成任何影響。

 

本示例方案將會放到框架的開源網站 http://pwmis.codeplex.com 上提供直接的下載,並且源碼已經全部提交,可以通過下麵地址查看詳細的代碼說明:

http://pwmis.codeplex.com/SourceControl/latest#SOD/Example/WinFormMvvm/WinFormMvvm/Readme.txt

 

瞭解更多信息或者加入社區QQ群討論,或者捐助本框架,請移步框架官網:

http://www.pwmis.com/sqlmap

 

感謝你選擇SOD框架,相信它能夠為你的開髮帶來很大的便利!

 

 

 

SOD開發團隊

深藍醫生

2016.11.13

------------PS---------------

感謝SOD開發團隊的 @廣州-銀古 同學,他已經及時將SOD框架的 nuget包更新到了最新版本,沒有前面說的 nuget包問題了。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先導入所需的jar包,項目目錄結構如下: 之後需要配置一下web.xml文件,內容如下: 然後配置applicationContext.xml: 下麵開始建立實體類User.java: 然後是控制層代碼: 這裡的value即訪問路徑,而return的"hello"通過applicationCont ...
  • 對比學習Python與Cstr1 = 'hello python 2'# 字元串i = 3.1415926535print(str1)print("hello python\n")# print 自帶換行符print('%s'%str1)print(str1)print("你好,%s OK %d" ... ...
  • 【轉載自】:http://blog.csdn.net/qq7342272/article/details/7940741 java運行時異常是可能在java虛擬機正常工作時拋出的異常。 java提供了兩種異常機制。一種是運行時異常(RuntimeExepction),一種是檢查式異常(checked ...
  • 多態成員變數的特點: 運行結果: 圖解: java中,子類的實例對象在堆記憶體中的存放應如圖所示,既有子類的成員變數,又有父類的成員變數; 同一對象可以有多態,當父類變數指向時,從A入口進入,可以訪問父類的所有成員變數;當子類變數指向時,從B入口進入,可以訪問子類的所有成員變數和父類非同名變數; ja ...
  • QThread Qt Gui frozen 未響應 阻塞 processEvents ...
  • 程式開發中,經常遇到一條記錄有多個狀態位,比如一條商品,他屬於熱門,新品,特賣。我們的資料庫如何設計呢? 一般有幾種方法 (1)建立關聯表 關聯表欄位:關係Id,商品Id,屬性Id 查詢:使用關聯表的方式,查詢某屬性的商品。 程式:寫入時,寫商品表和關聯表; (2)將多個屬性存在一個欄位中,用|分割 ...
  • 最近看到有部分招聘信息,要求應聘者說一下分散式系統架構的思路。今天早晨正好有些時間,我也把我們實際在.net方面網站架構的演化路線整理一下,只是我自己的一些想法,歡迎大家批評指正。 首先說明的是.net下開源內容較少,並且也不是做並行資料庫等基礎服務,因此在這裡什麼Hadoop、Spark、ZooK ...
  • StatementHandler 語句處理器,主要負責語句的創建、參數的設置、語句的執行。不負責結果集的處理。 BaseStatementHandler 實現公共部分,具體差異通過抽象方法,留給子類實現。 首先語句級別的配置,其次配置文件中的配置。 首先語句級別的配置,其次配置文件中的配置。 Sta ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...