I'm trying to build a Generic form component with Blazor. Currently, all other input types are working except for enums selects. I think this happens because the compiler doesn't know the specific enum type when trying to add the expression and callback functions:
public partial class GenericForm<ViewModel> : ComponentBase where ViewModel : new()
{
[Parameter]
public ViewModel Model { get; set; }
public readonly PropertyInfo[] Properties = typeof(ViewModel).GetProperties();
[Parameter] public EventCallback<ViewModel> OnValidSubmit { get; set; }
protected override async Task OnInitializedAsync()
{
if (Model == null)
{
Model = new ViewModel();
}
await base.OnInitializedAsync();
}
public RenderFragment CreateComponent(PropertyInfo property) => builder =>
{
var typeCode = Type.GetTypeCode(property.PropertyType);
if (property.PropertyType.IsEnum)
{
BuildEnumComponent(builder,property);
}
else
{
switch (typeCode)
{
case TypeCode.Int32:
BuildComponent<double>(property, builder, typeof(InputNumber<double>));
break;
case TypeCode.Int64:
BuildComponent<long>(property, builder, typeof(InputNumber<long>));
break;
case TypeCode.Int16:
BuildComponent<int>(property, builder, typeof(InputNumber<int>));
break;
case TypeCode.Decimal:
BuildComponent<decimal>(property, builder, typeof(InputNumber<decimal>));
break;
case TypeCode.String:
BuildComponent<string>(property, builder, typeof(InputText));
break;
case TypeCode.Boolean:
BuildComponent<bool>(property, builder, typeof(InputCheckbox));
break;
case TypeCode.DateTime:
BuildComponent<DateTime>(property, builder, typeof(InputDate<DateTime>));
break;
default:
Console.WriteLine("Unknown property type");
break;
}
}
};
private void BuildEnumComponent(RenderTreeBuilder builder,PropertyInfo property)
{
Guid id = Guid.NewGuid();
builder.AddMarkupContent(1, $"<label for=\"{id}\">{property.Name}</label>");
builder.OpenElement(2, "select");
builder.AddAttribute(3, "id", id.ToString());
builder.AddAttribute(4, "Value", Enum.GetValues(property.PropertyType).GetValue(0));
builder.AddAttribute(5, "ValueChanged", CreateCallback<Enum>(property));
builder.AddAttribute(6, "ValueExpression", CreateExpression<Enum>(property));
foreach (var value in Enum.GetValues(property.PropertyType))
{
builder.OpenElement(1, "option");
builder.AddAttribute(2, "value", value.ToString());
builder.CloseElement();
}
builder.CloseElement();
}
private void BuildComponent<PropertyType>(PropertyInfo property, RenderTreeBuilder builder, Type inputType)
{
var propertyValue = property.GetValue(Model);
var id = Guid.NewGuid();
builder.AddMarkupContent(0, $"<label for=\"{id}\">{property.Name}</label>");
builder.OpenComponent(1, inputType);
builder.AddAttribute(2, "id", id.ToString());
builder.AddAttribute(3, "Value", propertyValue);
builder.AddAttribute(5, "ValueChanged", CreateCallback<PropertyType>(property));
builder.AddAttribute(6, "ValueExpression", CreateExpression<PropertyType>(property));
builder.CloseComponent();
}
private EventCallback<PropertyType> CreateCallback<PropertyType>(PropertyInfo property)
{
return RuntimeHelpers.TypeCheck(EventCallback.Factory.Create(this, EventCallback.Factory.CreateInferred(this, __value => property.SetValue(Model, __value), (PropertyType)property.GetValue(Model))));
}
private Expression<Func<PropertyType>> CreateExpression<PropertyType>(PropertyInfo property)
{
var constant = Expression.Constant(Model, Model.GetType());
var exp = Expression.Property(constant, property.Name);
return Expression.Lambda<Func<PropertyType>>(exp);
}
}
Its crashing in this line: return Expression.Lambda<Func<PropertyType>>(exp);
with this error: System.ArgumentException: 'Expression of type 'Backender.Core.Common.Enums.EntityFieldType' cannot be used for return type 'System.Enum''
. EntityFieldType is also an enum. Any tips?
Aucun commentaire:
Enregistrer un commentaire