Prism使用Options選項

来源:https://www.cnblogs.com/louzixl/archive/2023/12/05/17877961.html
-Advertisement-
Play Games

Options是微軟提供的選項模塊,該模塊依賴於容器使用。除了微軟的IServiceCollection,當然也可以使用其它的依賴註入容器。本文演示如何在prism中使用Options。 創建應用項目 創建一個Avalonia應用(或其它類型應用),然後使用NuGet包管理器添加Prism.DryI ...


Options是微軟提供的選項模塊,該模塊依賴於容器使用。除了微軟的IServiceCollection,當然也可以使用其它的依賴註入容器。本文演示如何在prism中使用Options。

創建應用項目

創建一個Avalonia應用(或其它類型應用),然後使用NuGet包管理器添加Prism.DryIoc.Avalonia包。創建Views和ViewModels文件夾,將MainWindow移動到Views文件夾中(註意修改namespace),在ViewModels文件夾中創建MainWindowViewModel,以便Prism自動綁定ViewModel。

public partial class App : PrismApplication
{
    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
        base.Initialize();
    }

    protected override AvaloniaObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.Register<MainWindow>();
    }
}

添加Options功能

  • 首先使用NuGet添加Microsoft.Extentions.Options和Microsoft.Extensions.Options.ConfigurationExtensions。使用json配置文件進行測試,因此再添加上Microsoft.Extensions.Configuration.Json及Microsoft.Extensions.Configuration.Binder。

  • 添加Options靜態類,提供DefaultName:

public static class Options
{
    public static readonly string DefaultName = string.Empty;
    internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMembers =
        DynamicallyAccessedMemberTypes.PublicParameterlessConstructor;
}
  • 由於UnnamedOptionsManager為內部類,無法直接使用,因此添加一個UnnamedOptionsManager類,實現IOptions<>介面,直接拷貝源碼即可:
public class UnnamedOptionsManager<[DynamicallyAccessedMembers(Options.DynamicallyAccessedMembers)] TOptions> :
    IOptions<TOptions>
    where TOptions : class
{
    private readonly IOptionsFactory<TOptions> _factory;
    private volatile object _syncObj;
    private volatile TOptions _value;

    public UnnamedOptionsManager(IOptionsFactory<TOptions> factory) => _factory = factory;

    public TOptions Value
    {
        get
        {
            if (_value is TOptions value)
                return value;

            lock (_syncObj ?? Interlocked.CompareExchange(ref _syncObj, new object(), null) ?? _syncObj)
            {
                return _value ??= _factory.Create(Options.DefaultName);
            }
        }
    }
}
  • 添加OptionsPrismExtensions擴展類,添加AddOptions擴展方法,將選項泛型介面、工廠、緩存註冊到容器中。工廠註冊為瞬時,其它註冊為單例。客戶端不需要添加IOptionsSnapshot,只添加IOptions<>和IOptionsMonitor<>即可,前者獲取選項不會監聽修改,後者可以監聽選項修改:
public static class OptionsPrismExtensions
{
    public static IContainerExtension AddOptions(this IContainerExtension container)
    {
        ArgumentNullException.ThrowIfNull(container, nameof(container));

        container.RegisterSingleton(typeof(IOptions<>), typeof(UnnamedOptionsManager<>));
        container.RegisterSingleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>));
        container.Register(typeof(IOptionsFactory<>), typeof(OptionsFactory<>));
        container.RegisterSingleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>));
        return container;
    }
}
  • 添加OptionsConfigurationPrismExtensions擴展類,提供Configuration相關的擴展方法,可以直接將選項和配置Section進行綁定:
public static class OptionsConfigurationPrismExtensions
{
    public static IContainerExtension Configure<[DynamicallyAccessedMembers(
        DynamicallyAccessedMemberTypes.All)] TOptions>(this IContainerExtension container, 
        IConfiguration config) where TOptions : class
        => container.Configure<TOptions>(Options.DefaultName, config, _ => { });

    public static IContainerExtension Configure<[DynamicallyAccessedMembers(
        DynamicallyAccessedMemberTypes.All)] TOptions>(this IContainerExtension container, 
        string name, IConfiguration config, Action<BinderOptions> configureBinder)
        where TOptions : class
    {
        ArgumentNullException.ThrowIfNull(container, nameof(container));
        ArgumentNullException.ThrowIfNull(config, nameof(config));
    
        container.AddOptions();
        container.RegisterInstance<IOptionsChangeTokenSource<TOptions>>(
            new ConfigurationChangeTokenSource<TOptions>(name, config));
        container.RegisterInstance<IConfigureOptions<TOptions>>(
            new NamedConfigureFromConfigurationOptions<TOptions>(name, config, configureBinder));
    
        return container;
    }
}

使用

  • 添加一個settings.json配置文件,設置屬性複製到輸出目錄:如果較新則複製:
{
  "Test": {
    "Name": "louzi",
    "Age": 18,
    "Sex": "Male"
  }
}
  • 添加Test對應的Option實體:
public class TestOption
{
    public string Name { get; set; }

    public int Age { get; set; }

    public Gender Sex { get; set; }
}

public enum Gender
{
    Male,
    Female
}
  • 創建IConfiguration並綁定到選項:
// App
protected override IContainerExtension CreateContainerExtension()
{
    var container =  base.CreateContainerExtension();

    IConfiguration config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("settings.json", optional: true, reloadOnChange: true).Build();
    container.AddOptions().Configure<TestOption>(config.GetSection("Test"));

    return container;
}
  • ViewModel中通過依賴註入獲取選項:
public class MainWindowViewModel : BindableBase
{
    private string _name;
    private int _age;
    private Gender _sex;

    public MainWindowViewModel(IOptions<TestOption> options)
    {
        var testOption = options.Value;
        _name = testOption.Name;
        _age = testOption.Age;
        _sex = testOption.Sex;
    }

    public string Name { get => _name; set => SetProperty(ref _name, value); }

    public int Age { get => _age; set => SetProperty(ref _age, value); }

    public Gender Sex { get => _sex; set => SetProperty(ref _sex, value); }
}
  • View中顯示
<Grid RowDefinitions="1*,1*,1*" ColumnDefinitions="1*,1*">
	<TextBlock Text="Name: " TextAlignment="Right"/>
	<TextBlock Text="{Binding Name}" Grid.Column="1"/>
	<TextBlock Text="Age: " Grid.Row="1" TextAlignment="Right"/>
	<TextBlock Text="{Binding Age}" Grid.Row="1" Grid.Column="1"/>
	<TextBlock Text="Sex: " Grid.Row="2" TextAlignment="Right"/>
	<TextBlock Text="{Binding Sex}" Grid.Row="2" Grid.Column="1"/>
</Grid>

項目結構及運行效果如下圖:

轉載請註明出處,歡迎交流。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SSM框架中各層次作用及其關係(一) 平常學習生活中看見許多框架中的層次,都會有點懵,不知其意,抑或是看了又忘,所以這就是這篇短文的目的 總體辨析 JAVASSM(Java Web Application with Spring, Spring MVC, and MyBatis)是一種基於Java技 ...
  • 9 Docker 在 Docker 鏡像層內預覽文件 現在可以在 Services(服務)工具視窗中輕鬆訪問和預覽 Docker 鏡像層的內容。 從列表選擇鏡像,選擇 Show layers(顯示層),然後點擊 Analyze image for more information(分析鏡像以獲得更多 ...
  • 原文: https://openaigptguide.com/chatgpt-similar%20software/ ChatGPT是一款由美國OpenAI公司開發的人工智慧語言模型,類似的軟體有: 火山寫作(Volcano Writing):它是一款用戶友好的寫作軟體,可以自動生成具有創造性和連貫 ...
  • 前言 我python開發的GUI界面(圖形用戶界面)一直是tkinter,打包exe一直是Pyinstaller。但是打包出來的exe圖標、狀態欄圖標、窗體左上角圖標一直是預設的羽毛,我想自定義。 效果 最後使用base64創建臨時ico解決了該問題 步驟 創建icoToBase64.py,內容如下 ...
  • 在Java 21中,除了推出很多新特性之外,一些Bug修複,也需要註意一下。因為這些改變可能在升級的時候,造成影響。 Double.toString()和Float.toString()的精度問題修複 比如:對於Double.String(1e23): 在Java 19後,輸出內容為:1.0E23 ...
  • webjars類型的前端jar包 我們可以將公用的js,css,html,vue,shtml打包成一個jar,然後在其他項目中引用,這樣就不用每個項目都去引用一遍了,這樣就可以實現前端的公用了。 1.創建一個maven項目,添加依賴和插件 <dependencies> <!-- 依賴webjars- ...
  • pdf轉docx文檔是一個非常實用的功能,我只是簡單地實現了一個可視化界面供用戶操作。我這麼做的目的之一是想更多地掌握gradio的使用方法,同時也加強對Python流行第三方包的熟悉程度,因為這些第三方包是快速開發的關鍵。我也希望你能從中有所收穫,我已經公佈了本期的源碼地址,如果你覺得還不錯,或者... ...
  • 1. 什麼是Mvc 模型-視圖-控制器 (MVC) 體繫結構模式將應用程式分成 3 個主要組件組:視圖模型、視圖和控制器。 此模式有助於實現關註點分離。 使用此模式,用戶請求被路由到控制器,後者負責使用模型來執行用戶操作和/或檢索查詢結果。 控制器選擇要顯示給用戶的視圖,併為其提供所需的任何模型數據 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 微服務架構已經成為搭建高效、可擴展系統的關鍵技術之一,然而,現有許多微服務框架往往過於複雜,使得我們普通開發者難以快速上手並體驗到微服務帶了的便利。為瞭解決這一問題,於是作者精心打造了一款最接地氣的 .NET 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...