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
  • 下麵是一個標準的IDistributedCache用例: public class SomeService(IDistributedCache cache) { public async Task<SomeInformation> GetSomeInformationAsync (string na ...
  • 這個庫提供了在啟動期間實例化已註冊的單例,而不是在首次使用它時實例化。 單例通常在首次使用時創建,這可能會導致響應傳入請求的延遲高於平時。在註冊時創建實例有助於防止第一次Request請求的SLA 以往我們要在註冊的時候實例單例可能會這樣寫: //註冊: services.AddSingleton< ...
  • 最近公司的很多項目都要改單點登錄了,不過大部分都還沒敲定,目前立刻要做的就只有一個比較老的項目 先改一個試試手,主要目標就是最短最快實現功能 首先因為要保留原登錄方式,所以頁面上的改動就是在原來登錄頁面下加一個SSO登錄入口 用超鏈接寫的入口,頁面改造後如下圖: 其中超鏈接的 href="Staff ...
  • Like運算符很好用,特別是它所提供的其中*、?這兩種通配符,在Windows文件系統和各類項目中運用非常廣泛。 但Like運算符僅在VB中支持,在C#中,如何實現呢? 以下是關於LikeString的四種實現方式,其中第四種為Regex正則表達式實現,且在.NET Standard 2.0及以上平... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他們的程式記憶體會偶發性暴漲,自己分析了下是非托管記憶體問題,讓我幫忙看下怎麼回事?哈哈,看到這個dump我還是非常有興趣的,居然還有這種游戲幣自助機類型的程式,下次去大玩家看看他們出幣的機器後端是不是C#寫的?由於dump是linux上的程式,剛好win ...
  • 前言 大家好,我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的,可以參考我的另一個項目: 手寫從零實現簡易版 tomcat minicat 手寫 ngin ...
  • 上一次的介紹,主要圍繞如何統一去捕獲異常,以及為每一種異常添加自己的Mapper實現,並且我們知道,當在ExceptionMapper中返回非200的Response,不支持application/json的響應類型,而是寫死的text/plain類型。 Filter為二方包異常手動捕獲 參考:ht ...
  • 大家好,我是R哥。 今天分享一個爽飛了的面試輔導 case: 這個杭州兄弟空窗期 1 個月+,面試了 6 家公司 0 Offer,不知道問題出在哪,難道是杭州的 IT 崩盤了麽? 報名面試輔導後,經過一個多月的輔導打磨,現在成功入職某上市公司,漲薪 30%+,955 工作制,不咋加班,還不捲。 其他 ...
  • 引入依賴 <!--Freemarker wls--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> ...
  • 你應如何運行程式 互動式命令模式 開始一個互動式會話 一般是在操作系統命令行下輸入python,且不帶任何參數 系統路徑 如果沒有設置系統的PATH環境變數來包括Python的安裝路徑,可能需要機器上Python可執行文件的完整路徑來代替python 運行的位置:代碼位置 不要輸入的內容:提示符和註 ...