一個能夠根據對象或者類型自動生成頁面元件的Blazor WebAssembly應用
- Github ma-hua/blazor-auto
- 基于Ant.Design-Blazor元件庫
- 需要dotnet-sdk v3.1.6及以上
一個能夠根據對象或者類型自動生成頁面元件的Blazor WebAssembly應用 一個能夠根據對象或者類型自動生成頁面元件的Blazor WebAssembly應用
需求描述
- 優惠活動相關業務需求常常變更頻繁,基于Sql Server中json存儲技術,對公司原先的體系展開重構。将活動規則劃分為多個大類,每一類的對象不再以字段對應的方式存儲在資料庫中,而是以Json的方式存儲,這樣需要增加或者删除某些字段的時候,隻需要修改相應實體,而不必修改資料庫設計。
- 之後也對活動管理系統提出新的要求,即能夠根據最新釋出的包含活動實體的Nuget包,自動生成規則設定頁面。基于html+js的前端技術或許并不能做到這一點,是以提出了使用Blazor技術+C#,來完成這一目标:根據對象或者類型自動生成頁面元件,并且完成資料綁定,來完成新增或編輯等操作。
項目介紹
本項目僅用于學習參考,本人才疏學淺,不足之處還請多多指教
- Blazor.Auto 包含反射與字段描述等相關工具
- Blazor.Auto.Components 根據字段描述符來自動完成資料綁定的元件庫(基于Ant.Design-Blazor)
擷取字段主要資訊
- 字段描述符 FieldDescriptor 包含字段名,字段描述,IsRequired,值描述符
- 值描述符 ValueDescriptor 包含值的類型,值,下拉框清單
字段元件:輸入框 日期選擇器 開關 清單選擇器
- 根據值類型,輸入框分為:字元串輸入框,整數輸入框,小數輸入框
- 開關分為可控開關和非空開關(bool?和bool兩種)
- 清單選擇器以模态框的形式展示,分為單選清單和多選清單
字段元件均繼承自父元件BaseComponent,父元件中包含虛方法ValueChangedCallBack,以連結綁定的方式來完成參數綁定。
清單選擇器
清單選擇器通常對應類型為List<T>的字段,選擇器内容的擷取較為關鍵。假如泛型類型是枚舉的話,可以直接通過反射技術拿到選擇清單。
但是如果需要通過查詢某些接口來擷取選擇清單的話,需要實作ISelectItemProvider接口。并且為其實作類指定一個Keyword,在字段上使用特性[SelectDescriptionAttribute]标注同樣的Keyword。那麼在生成元件時,可以通過Keyword從IOC容器中擷取SelectItemProvider,并調用實作方法,來擷取選擇項。
通常需要使用Named的方式注入ISelectItemProvider實作類,在本項目中,我使用的是Autofac容器。
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
//注入ISelectItemProvider實作類
builder.ConfigureContainer(new AutofacServiceProviderFactory(cfg =>
{
cfg.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
cfg.RegisterType<StoreGroupProvider>().Named<ISelectItemProvider>(StoreGroupProvider.Keyword).SingleInstance();
cfg.RegisterType<PriceGroupProvider>().Named<ISelectItemProvider>(PriceGroupProvider.Keyword).SingleInstance();
}));
在清單選擇器元件中,根據字段的Keyword從IOC容器中擷取選擇清單項
[Inject]
public IComponentContext ComponentContext { get; set; }
protected override async Task OnParametersSetAsync()
{
if (!ValueComponentExtension.IsEnumSelect(Descriptor.Value) && !string.IsNullOrWhiteSpace(Keyword))
{
try
{
Items = await ComponentContext.ResolveNamed<ISelectItemProvider>(Keyword).GetSelectItemAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}