如何在Blazor中用工厂模式消除调用Razor组件的If/else语句
在Blazor中实现组件工厂模式的方案
1. 定义基础模型与枚举
先统一共用的问题模型和样式枚举:
public enum QuestionStyle { TextInput, Dropdown, CheckboxGroup } public class Question { public int Id { get; set; } public string Title { get; set; } public QuestionStyle Style { get; set; } // 其他通用属性根据需求添加 }
2. 创建组件统一接口
定义接口确保所有问题组件遵循相同的参数规范:
public interface IQuestionComponent { Question Question { get; set; } }
3. 实现自定义组件
每个组件继承ComponentBase并实现上述接口,以文本输入组件为例:
@inherits ComponentBase @implements IQuestionComponent <div class="text-input-question"> <label>@Question.Title</label> <input type="text" /> </div> @code { [Parameter] public Question Question { get; set; } }
Dropdown、CheckboxGroup等组件按相同结构实现,保证[Parameter]属性与接口一致。
4. 实现组件工厂类
工厂负责维护样式与组件类型的映射,支持动态扩展:
public class QuestionComponentFactory { private readonly Dictionary<QuestionStyle, Type> _componentMap = new(); public QuestionComponentFactory() { // 初始化注册现有组件 _componentMap.Add(QuestionStyle.TextInput, typeof(TextInputComponent)); _componentMap.Add(QuestionStyle.Dropdown, typeof(DropdownComponent)); _componentMap.Add(QuestionStyle.CheckboxGroup, typeof(CheckboxGroupComponent)); } // 提供扩展方法,新增组件时直接注册 public void RegisterComponent(QuestionStyle style, Type componentType) { if (_componentMap.ContainsKey(style)) _componentMap[style] = componentType; else _componentMap.Add(style, componentType); } // 根据问题获取对应组件类型 public Type GetComponentType(Question question) { if (_componentMap.TryGetValue(question.Style, out var type)) return type; // 找不到对应样式时返回默认组件(可根据需求调整) return typeof(TextInputComponent); } }
在Program.cs中将工厂注册为单例:
builder.Services.AddSingleton<QuestionComponentFactory>();
5. 页面动态渲染组件
在主页面注入工厂,通过DynamicComponent(.NET 6+支持)动态渲染组件:
@inject QuestionComponentFactory ComponentFactory @foreach (var question in Questions) { <DynamicComponent Type="ComponentFactory.GetComponentType(question)" Parameters="new Dictionary<string, object> { { nameof(IQuestionComponent.Question), question } }" /> } @code { [Parameter] public List<Question> Questions { get; set; } = new(); }
扩展新组件的方式
当需要新增一种问题样式(比如日期选择器):
- 创建
DatePickerComponent,实现IQuestionComponent接口 - 在
Program.cs中注册映射:
var factory = app.Services.GetRequiredService<QuestionComponentFactory>(); factory.RegisterComponent(QuestionStyle.DatePicker, typeof(DatePickerComponent));
全程无需修改主页面或工厂核心代码,完全符合开闭原则。
内容的提问来源于stack exchange,提问作者maikson mendes
相关产品推荐
相关产品推荐

