private void BuildComponent <FValue>(RenderTreeBuilder builder, FieldData fieldData) { FValue value = (FValue)fieldData.PropertyInfo.GetValue(Model); // build up the access method var constant = Expression.Constant(Model, Model !.GetType()); var exp = Expression.Property(constant, fieldData.Name); var valueExpression = Expression.Lambda <Func <FValue> >(exp); // build the event callback, include a notification that the field has updated as well as the model var valueChanged = Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck( EventCallback.Factory.Create <FValue?>( this, EventCallback.Factory.CreateInferred( this, __value => { fieldData.PropertyInfo.SetValue(Model, __value); ModelChanged.InvokeAsync(Model); }, value ) ) ); // put our surrogate component in the render pipeline // parsing in the needed variable that will be loading into it as params by the infrastructure (magic) var elementType = typeof(PlaceHolderComponent <FValue>); builder.OpenComponent(0, elementType); builder.AddAttribute(1, nameof(PlaceHolderComponent <FValue> .FieldData), fieldData); builder.AddAttribute(2, nameof(PlaceHolderComponent <FValue> .Value), value); builder.AddAttribute(3, nameof(PlaceHolderComponent <FValue> .ValueExpression), valueExpression); builder.AddAttribute(4, nameof(PlaceHolderComponent <FValue> .ValueChanged), valueChanged); builder.AddAttribute(5, nameof(PlaceHolderComponent <FValue> .ReadOnly), ReadOnly); builder.AddAttribute(6, nameof(PlaceHolderComponent <FValue> .UseValidationMessages), UseValidationMessages); builder.CloseComponent(); }