[WPF]本地化入門

来源:http://www.cnblogs.com/dino623/archive/2017/12/10/LocalizationWPF.html
-Advertisement-
Play Games

1. 前言 WPF的本地化是個很常見的功能,我做過的WPF程式大部分都實現了本地化(不管最終有沒有用到)。通常本地化有以下幾點需求: 在程式啟動時根據 "CultureInfo.CurrentUICulture" 或配置項顯示對應語言的UI。 在程式運行時可以動態切換UI語言(無需重啟程式)。 製作 ...


1. 前言

WPF的本地化是個很常見的功能,我做過的WPF程式大部分都實現了本地化(不管最終有沒有用到)。通常本地化有以下幾點需求:

  • 在程式啟動時根據CultureInfo.CurrentUICulture或配置項顯示對應語言的UI。
  • 在程式運行時可以動態切換UI語言(無需重啟程式)。
  • 製作對應不同語言的安裝包。
  • 通過下載語言包實現多種語言的本地化。

其中只有第一點是必要的。
第二點最好也可以實現,很多時候切換語言只為了看看某個專業術語在英語中的原文是什麼,或者臨時列印個英文報表,平時使用還是用中文,用戶不想為了這點重啟程式。
第三點和第四點雖然很常見,但我從來沒實現過,畢竟文字資源(有時還有少量圖片)占用的空間不會太多,大部分WPF程式都沒有大到需要考慮安裝包大小,所有語言的資源全部打包進一個安裝包就可以了。

WPF本地化技術很成熟,也有幾種方案,微軟在MSDN給出了詳細的介紹WPF 全球化和本地化概述,還有一份古老的文檔WPF Localization Guidance,整整66頁,裡面詳細介紹了各種WPF本地化的機制。

本文只介紹兩種實現以上第1、2點需求的方案。

2. 使用資源詞典

2.1 基本原理

對WPF開發者來說,資源詞典肯定不會陌生。不過在資源詞典里使用string可能比較少。

<Window x:Class="LocalizationDemoWpf.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LocalizationDemoWpf"
        mc:Ignorable="d" 
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <system:String x:Key="Chinese">中文</system:String>
    </Window.Resources>
    <Grid>
        <TextBlock Text="{DynamicResource Chinese}"/>
    </Grid>
</Window>

如以上代碼所示,在XAML中定義string資源需要先引入 xmlns:system="clr-namespace:System;assembly=mscorlib"命名空間,之後再使用DynamicResource引用這個資源。不要使用StaticResource,這樣沒法做到動態切換語言。

要使用資源詞典實現本地化,需要先創建所需語言的xaml,我在DEMO中創建了en-us.xaml和zh-cn.xaml兩個資源詞典,裡面的包含的資源結構一致(指數量和Key一樣):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:system="clr-namespace:System;assembly=mscorlib"
                    xmlns:local="clr-namespace:LocalizationDemoWpf">
    <system:String x:Key="SwitchLanguage">切換語言</system:String>
    <system:String x:Key="Chinese">中文</system:String>
    <system:String x:Key="English">英文</system:String>
    <system:String x:Key="Username">用戶名</system:String>
    <system:String x:Key="Sex">性別</system:String>
    <system:String x:Key="Address">地址</system:String>
    <SolidColorBrush x:Key="Background" Color="#88FF0000"/>
</ResourceDictionary>

在程式啟動時根據CultureInfo.CurrentUICulture或配置項選擇對應的資源詞典,使用MergedDictionaries的方式載入到程式的資源集合中:

var culture = ReadCultureFromConfig();
var cultureInfo = new System.Globalization.CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;


ResourceDictionary dictionary = new ResourceDictionary { Source = new Uri($@"Resources\{culture}.xaml", UriKind.RelativeOrAbsolute) };
Application.Current.Resources.MergedDictionaries[0] = dictionary;

這樣本地化的功能就完成了。

2.2 動態切換語言

其實上述方案已實現了動態切換語言。
XAML資源的引用原則是就近原則,這個就近不僅指VisualTree上的就近,還指時間上的就近。後添加進資源詞典的資源將替換之前的同名資源。使用DynamicResource而不是StaticResource,就是為了在資源被替換時能實時變更UI的顯示。

2.3 設計時支持

VisualStudio的XAML設計時支持對開發WPF程式至關重要,對本地化來說,設計時支持主要包含3部分:

  • 在編寫XAML時可以得到資源的智能感知
  • 有完整的設計視圖
  • 在不同語言之間切換

使用資源詞典實現本地化,只需在App.xaml中合併對應的資源詞典即可獲得完整的設計時支持。

<Application x:Class="LocalizationDemoWpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:LocalizationDemoWpf"
             xmlns:resource="clr-namespace:LocalizationDemoWpf.Resource;assembly=LocalizationDemoWpf.Resource"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/zh-cn.xaml"/>
                <!--<ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/en-us.xaml"/>-->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

這段XAML只是為了提高設計時體驗,沒有也能通過編譯。

2.4 在代碼里訪問資源

在代碼中訪問資源比較麻煩,需要知道資源的名稱,而且沒有智能感知,如果資源詞典由第三方類庫提供就會更麻煩。

var message = TryFindResource("SwitchLanguage") as string;
if (string.IsNullOrWhiteSpace(message) == false)
    MessageBox.Show(message);

2.5 在代碼里替換資源

private void OnReplaceString(object sender, RoutedEventArgs e)
{
    _totalReplace++;
    string content = "Replace " + _totalReplace;
    Resources["StringToReplace"] = content;
}

如上所示,在代碼中替換資源十分簡單,不過這種簡單也帶來了資源不可控的問題。

2.6 在程式集之間共用資源

上面有提過,在獲取第三方類庫中某個資源十分麻煩,不僅如此,連獲得第三方類庫中的資源詞典名稱都十分麻煩。我建議在類庫中定義如下的類,可以給開發者提供一些方便:

public static class Resources
{
    public static Uri EnglishResourceUri { get; } =
        new Uri("/LocalizationDemoWpf.Resource;component/Resource.en-us.xaml", UriKind.RelativeOrAbsolute);

    public static Uri ChineseResourceUri { get; } =
        new Uri("/LocalizationDemoWpf.Resource;component/Resource.zh-cn.xaml", UriKind.RelativeOrAbsolute);
}

2.7 總結

資源詞典是實現本地化的一種很常見的方式,它有如下優點:

  • 簡單易用,而且容易理解。
  • XAML語法簡單。
  • 資源可以是除string以外的類型,如SolidColorBrush。

但這種方式的缺點也不少:

  • 難以管理,一旦資源過多,重名、互相覆蓋、智能感知列表過長等問題將極大地影響開發,就連保證不同語言間資源詞典里的資源數量一致都很麻煩。
  • 在程式集之間難以共用,引用很簡單,但由於沒有智能感知將很難使用,而且不同程式集之間的資源同名更難以跟蹤。

除此以外,在動態切換語言上還存在一些問題。下麵這段XAML就沒法做到動態切換語言:

<DataGrid Grid.Row="1" Margin="5">
    <DataGrid.Columns>
        <DataGridTextColumn Header="{DynamicResource Username}"/>
        <DataGridTextColumn Header="{DynamicResource Sex}"/>
        <DataGridTextColumn Header="{DynamicResource Address}" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

在DataGridColumn的Header上做動態切換語言,需要寫成DataTemplate的方式:

<DataGrid Grid.Row="2" Margin="5">
    <DataGrid.Columns>
        <DataGridTextColumn >
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Username}"/
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        <DataGridTextColumn >
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Sex}"/>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        <DataGridTextColumn Width="*">
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate >
                    <TextBlock Text="{DynamicResource Address}"/>
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

3. 使用Resx資源文件

3.1 基本原理

比起資源詞典,我更喜歡使用Resx資源文件,不過這種方式語法複雜一些,而且也有不少小問題。
在VisualStudio中創建尾碼名為resx的資源文件並打開,可在以下UI編輯資源文件的值(將訪問修飾符改為public用起來方便些):

在修改資源文件的值後PublicResXFileCodeGenerator將自動創建對應的類併為每一個鍵值添加如下代碼:

/// <summary>
///   查找類似 Address 的本地化字元串。
/// </summary>
public static string Address {
    get {
        return ResourceManager.GetString("Address", resourceCulture);
    }
}

然後將這個資源文件複製粘貼一份,將名稱改為“原名+.+對應的語言+.resx”的格式,並且將裡面的值翻譯成對應語言如下:

在UI上使用x:Static綁定到對應的資源:

<DataGridTextColumn Header="{x:Static local:Labels.Username}"/>

這樣基本的本地化就完成了。很多控制項庫都是使用這種方式做本地化。除了字元串,resx資源文件還支持除字元串以外的資源,如圖片、音頻等。

但是這個方案只實現了最基本的本地化,而且最大的問題是只支持直接使用字元串,不支持TypeConverter,甚至也不支持除字元串以外的其它XAML內置類型(即Boolea,Char,Decimal,Single,Double,Int16,Int32,Int64,TimeSpan,Uri,Byte,Array等類型)。例如使用Label.resx中名為Background值為 #880000FF 的字元串為Grid.Background實現本地化:

Labels.designer.resx

/// <summary>
///   查找類似 #880000FF 的本地化字元串。
/// </summary>
public static string Background {
    get {
        return ResourceManager.GetString("Background", resourceCulture);
    }
}

MainWindow.xaml

<Grid  Background="{x:Static local:Labels.Background}"/>

運行時報錯:ArgumentException: “#88FF0000”不是屬性“Background”的有效值。

這樣資源文件的實用性大打折扣。當然,這個方案也不支持動態切換語言。

3.2 動態切換語言

Silverlight中已沒有了x:Static的綁定方式,改為使用Binding實現本地化,這樣雖然語法複雜一些,但更加實用。WPF當然也可以使用這種方式。

首先, 創建一個類封裝資源文件生成的類(在這個Demo中是Labels):

public class ApplicationResources
{
    public ApplicationResources()
    {
        Labels = new Labels();
    }

    public Labels Labels { get; set; }
}

然後在App.xaml中將這個類作為資源添加到資源集合中,為了以後使用的語法簡單些,我通常將Key取得很簡單:

<Application x:Class="LocalizationDemoWpfUsingResource.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:LocalizationDemoWpfUsingResource"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:ApplicationResources x:Key="R"  />
    </Application.Resources>
</Application>

最後在XAML中這樣綁定:

<DataGridTextColumn Header="{Binding Labels.Username, Source={StaticResource R}}"/>

這樣語法複雜一些,但也有很多好處:

  • 支持TypeConverter,這樣就可以使用除String以外的其它類型。
  • 支持Binding的其它功能,如IValueConverter。

麻煩的是,WPF似乎不是很喜歡這種方式,VisualStudio會提示這種錯誤,畢竟資源文件中的屬性都是static屬性,不是實例成員。幸運的是編譯一次這種錯誤提示就會消失。

將調用方式改為Binding以後就可以實現動態切換語言了。由於UI通過Binding獲取資源文件的內容,可以通過INotifyPropertyChanged通知UI更新。將ApplicationResources 改造一下:

public class ApplicationResources : INotifyPropertyChanged
{
    public static ApplicationResources Current { get; private set; }

    public ApplicationResources()
    {
        Current = this;
        Labels = new Labels();
    }

    public Labels Labels { get; set; }



    public event PropertyChangedEventHandler PropertyChanged;

    public  void ChangeCulture(System.Globalization.CultureInfo cultureInfo)
    {
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Labels.Culture = cultureInfo;

        if (Current != null)
            Current.RaiseProoertyChanged();
    }

    public void RaiseProoertyChanged()
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
    }
}

現在可以簡單地切換語言了。

var culture = ReadCultureFromConfig();
var cultureInfo = new System.Globalization.CultureInfo(culture);
ApplicationResources.Current.ChangeCulture(cultureInfo);

3.3 設計時支持

實現本地化的一個很麻煩的事情是如何在設計視圖看到各種語言下的效果。在使用資源詞典的方案中是通過在App.xaml中合併對應的資源詞典:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/zh-cn.xaml"/>
    <!--<ResourceDictionary Source="/LocalizationDemoWpf;component/Resources/en-us.xaml"/>-->
</ResourceDictionary.MergedDictionaries>

在資源文件的方案中,需要在ApplicationResources中添加一個屬性:

private string _language;

/// <summary>
/// 獲取或設置 Language 的值
/// </summary>
public string Language
{
    get { return _language; }
    set
    {
        if (_language == value)
            return;

        _language = value;
        var cultureInfo = new CultureInfo(value);
        Thread.CurrentThread.CurrentUICulture = cultureInfo;
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Labels.Culture = cultureInfo;

        RaiseProoertyChanged();
    }
}

之後在App.xaml中就可以通過改變這個屬性來改變設計時的UI的語言,在VS2017中連編譯都不需要就可以改變設計視圖的語言。

<local:ApplicationResources x:Key="R"  Language="zh-CN"/>

3.4 在代碼里訪問資源

在代碼里訪問資源文件的資源十分簡單:

MessageBox.Show(Labels.SwitchLanguage);

3.5 在代碼里替換資源

資源文件要實現這個需求就一點都不有趣了,至少我從未在實際工作中做過。最大的難題是資源文件生成的類中的屬性是靜態屬性,而且只有getter方法:

public static string StringToReplace {
    get {
        return ResourceManager.GetString("StringToReplace", resourceCulture);
    }
}

我們也可以創建一個派生類,強行替換對應的屬性:

public class ExtendLabels : Labels
{
    /// <summary>
    /// 獲取或設置 StringToReplace 的值
    /// </summary>
    public new string StringToReplace { get; set; }
}

然後替換ApplicationResources中的Labels,並且觸發PropertyChanged。不過這樣會刷新所有UI上的字元串等資源,只為了替換一個字元資源代價有點大,幸好一般來說並不會太消耗性能。

private void OnReplaceString(object sender, RoutedEventArgs e)
{
    _totalReplace++;
    string content = Labels.StringToReplace + " " + _totalReplace;
    if (_extendLabels == null)
        _extendLabels = new ExtendLabels();

    _extendLabels.StringToReplace = content;
    ApplicationResources.Current.Labels = _extendLabels;
    ApplicationResources.Current.RaiseProoertyChanged();
}

3.6 在程式集之間共用資源

只需要將資源文件的訪問修飾符改為public,無需其它操作就可以方便地在程式集之間共用資源。

3.7 管理資源文件

比起資源詞典,資源文件還有一個很大的優勢就是容易管理。Demo中只有一個名字Labels的資源文件,實際項目中可以按功能或模塊分別建立對應的資源文件,解決了資源詞典重名、互相覆蓋、智能感知列表過長等問題。另外我推薦使用VS的擴展程式ResXManager管理所有資源文件。

它可以在一個UI里管理所有語言的資源文件,極大地方便了資源文件的使用。

3.8 ReSharper支持

對Resx資源文件,ReSharper也提供了良好的支持。

當需要為某個資源修改Key時,可以按“資源文件名稱”+"."+"Key"來全局替換,通常這樣已經足夠放心。ReSharper更進一步,它提供了重命名功能。假設要將Labels的資源English重名為為Englishs,可以先在Labels.Designer.cs重命名,然後應用“Apply rename refactoring”選項:

這時所有引用,包括XAML都已應用新的名稱:

不過最後仍需自己動手在資源文件編輯器中修改Key。

除此之外,如果在XAML中使用了錯誤的Key,ReSharper也有錯誤提示:

在某些場合,ReShaper還可使用“Move To Resource”功能:

3.9 總結

使用Resx資源文件實現本地化有如下優點:

  • 資源管理方便。
  • 容易在代碼中使用。
  • 容易在程式集之間共用。
  • 支持TypeConverter,這樣就可以使用除String以外的其它類型。
  • 支持Binding的其它功能,如IValueConverter。
  • 相容性好,Silverlight及之後的XAML技術都可以使用。
  • 第三方工具支持。
  • 支持圖片、音頻等資源。

缺點如下:

  • XAML語法相對複雜。
  • 不能直接應用於TypeConverter不支持的類型,例如LinearGradientBrush。

雖然不能直接支持LinearGradientBrush,但也不是完全沒有辦法,只是複雜了許多,如分別對LinearGradientBrush的GradientStop做本地化:

<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="Black" Offset="0"/>
    <GradientStop Color="{Binding Source={StaticResource R},Path=Labels.Background}" Offset="1"/>
</LinearGradientBrush>

4. 結語

這篇文章只介紹了本地化的入門知識,其它還有很多本地化的要點,如驗證信息中的本地化沒有涉及。另外,本地化還可以使用x:Uid方式或WPFLocalizeExtension等方式實現,這裡就不詳細介紹。
WPF 全球化和本地化概述里有介紹一些本地化的最佳做法,如UI上應該使用相對佈局而非絕對佈局、字體選擇等,這裡不再累贅。

需要註意的是上述兩種方案都不適用於CLR屬性,這也是為什麼我一直強調UIElement的屬性最好是依賴屬性的原因之一。

如有錯漏請指出。

5. 參考

WPF 全球化和本地化概述
Silverlight 部署和本地化
WPFLocalizationExtension
WPF Localization Guidance
XAML Resources
CultureInfo 類
Supported languages

6. 源碼

LocalizationDemo


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

-Advertisement-
Play Games
更多相關文章
  •   枚舉是如何保證線程安全的且其在序列化和反序列化的操作中是單例的?   要想看源碼,首先得有一個類吧,那麼枚舉類型到底是什麼類呢?是enum嗎?答案很明顯不是,enum就和class一樣,只是一個關鍵字,他並不是一個類,那麼枚舉是由什麼類維護的呢,我們簡單的 ...
  • 用法一:常量   在JDK1.5 之前,我們定義常量都是: public static fianl....。現在好了,有了枚舉,可以把相關的常量分組到一個枚舉類型里,而且枚舉提供了比常量更多的方法。 用法二:switch   JDK1.6之前的switch語句 ...
  • 1.首先需要在操作系統上安裝Git分散式管理系統 此處自行百度。。。。。。。。。。。。。 2.在Intellij IDEA中配置Git 打開Settings(File-->Settings) --> 在搜索欄內輸入git,回車跳轉到Git配置頁面 --> 將git的運行路徑填入Path to Git ...
  • 背水一戰 Windows 10 之 控制項(控制項基類 - ContentControl, UserControl, Page): ContentPresenter, ContentControl, UserControl, Page ...
  • 返回總目錄 10 Form Template Method(塑造模板函數) 概要 你有一些子類,其中相應的某些函數以相同的順序執行類似的操作,但各個操作的細節不同。 將這些操作分別放進獨立的函數中,並保持它們都有相同的簽名,於是原函數也就變得相同了,然後將原函數上移至基類。 動機 繼承是避免重覆行為 ...
  • unity中會有像[range(0,1)]這樣的特性寫法,其非常方便的限制了變數範圍但是。我一直很好奇這是怎麼實現的,所以翻了翻其他博主對其的解釋和應用。 一,什麼是特性 有一種解釋我很能接受,特性就像牡蠣附在對象上。其本質也是一種對象,特殊之處在於其編譯時就存在了,也就是在程式運行之前就存在了。 ...
  • 註意:無論【協變】還是【逆變】都能 保證類型安全 ...
  • 今天練習C#的一個功能,就是將一個字元串時行翻轉顯示 如: 翻轉成為: 方法與寫法很多。 方法一: public void Reversal(string input) { string result = ""; for (int i = input.Length - 1; i >= 0; i--) ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...