再学Blazor——组件建造者
生活随笔
收集整理的這篇文章主要介紹了
再学Blazor——组件建造者
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
使用 RenderTreeBuilder 創建組件是 Blazor 的一種高級方案。前幾篇文中有這樣創建組件的示例 builder.Component<MyComponent>().Build(); ,本文主要介紹該高級方案的具體實現,我們采用測試驅動開發(TDD)方法,大致思路如下:
- 從測試示例入手
- 擴展一個RenderTreeBuilder類的泛型擴展方法,泛型類型為組件類型
- 創建組件建造者類(ComponentBuilder)提供方法來構建組件
- 通過組件的屬性選擇器來設置組件參數
- 構建時能返回組件的對象實例
1. 示例
首頁我們從一個我們預想的高級方案示例入手,然后逐漸分析并實現我們預想的方案。下面是預想的示例代碼:
class MyComponent : ComponentBase
{
private MyTest test; //MyTest組件的對象實例
//覆寫構建呈現樹方法
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.Component<MyTest>()
.Set(c => c.Title, "Hello") //設置MyTest組件Title參數
.Build(value => test = value); //建造組件并給MyTest實例賦值
}
}
2. 擴展方法
下面實現builder.Component<MyTest>()這行代碼,這是RenderTreeBuilder的一個擴展方法,該方法返回組件建造者類(ComponentBuilder)。
public static class Extension
{
//泛型T是Blazor組件類型
public static ComponentBuilder<T> Component<T>(this RenderTreeBuilder builder) where T : notnull, IComponent
{
//返回一個組件建造者類對象,將builder傳遞給建造者
//其內部方法需要通過builder來構建組件
return new ComponentBuilder<T>(builder);
}
}
3. 建造者類
接下來實現組件建造者類(ComponentBuilder),該類是手動構建組件的核心代碼,提供設置組件參數以及構建方法。
public class ComponentBuilder<T> where T : IComponent
{
//手動構建呈現器
private readonly RenderTreeBuilder builder;
//組件參數字典,設置組件參數時,先存入字典,在構建時批量添加
internal readonly Dictionary<string, object> Parameters = new(StringComparer.Ordinal);
//構造函數
internal ComponentBuilder(RenderTreeBuilder builder)
{
this.builder = builder;
}
//添加組件參數方法,name為組件參數名稱,value為組件參數值
//提供Add方法可以添加非組件定義的屬性,例如html屬性
public ComponentBuilder<T> Add(string name, object value)
{
Parameters[name] = value; //將參數存入字典
return this; //返回this對象,可以流式操作
}
//設置組件參數方法,selector為組件參數屬性選擇器表達式,value為組件參數值
//使用選擇器有如下優點:
// - 當組件屬性名稱更改時,可自動替換
// - 通過表達式 c => c. 可以直接調出組件定義的屬性,方便閱讀
// - 可通過TValue直接限定屬性的類型,開發時即可編譯檢查
public ComponentBuilder<T> Set<TValue>(Expression<Func<T, TValue>> selector, TValue value)
{
var property = TypeHelper.Property(selector); //通過屬性選擇器表達式獲取組件參數屬性
return Add(property.Name, value); //添加組件參數
}
//組件構建方法,action為返回組件對象實例的委托,默認為空不返回實例
public void Build(Action<T> action = null)
{
builder.OpenComponent<T>(0); //開始附加組件
if (Parameters.Count > 0)
builder.AddMultipleAttributes(1, Parameters); //批量添加組件參數
if (action != null)
builder.AddComponentReferenceCapture(2, value => action.Invoke((T)value)); //返回組件對象實例
builder.CloseComponent(); //結束附加組件
}
}
4. 屬性選擇器
為什么要用屬性選擇器,組件建造者類中已經提到,下面介紹如何通過屬性選擇器表達式來獲取組件類型的屬性對象。
public class TypeHelper
{
//通過屬性選擇器表達式來獲取指定類型的屬性
public static PropertyInfo Property<T, TValue>(Expression<Func<T, TValue>> selector)
{
if (selector is null)
throw new ArgumentNullException(nameof(selector));
if (selector.Body is not MemberExpression expression || expression.Member is not PropertyInfo propInfoCandidate)
throw new ArgumentException($"The parameter selector '{selector}' does not resolve to a public property on the type '{typeof(T)}'.", nameof(selector));
var type = typeof(T);
var propertyInfo = propInfoCandidate.DeclaringType != type
? type.GetProperty(propInfoCandidate.Name, propInfoCandidate.PropertyType)
: propInfoCandidate;
if (propertyInfo is null)
throw new ArgumentException($"The parameter selector '{selector}' does not resolve to a public property on the type '{typeof(T)}'.", nameof(selector));
return propertyInfo;
}
}
5. 總結
以上就是組件建造者的完整實現過程,代碼不長,但這些功能足以完成手動構建Blazor組件的需求。
總結
以上是生活随笔為你收集整理的再学Blazor——组件建造者的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1029 最大公约数和最小公倍数问题(
- 下一篇: java信息管理系统总结_java实现科