1

Blazor - .NET Core 3 预览版 6

我正在尝试构建将属性作为 lambda 表达式的组件,然后为用户提供有关该属性的信息。

如果我声明对象并将其直接绑定为组件上的表达式,我似乎能够获取所有数据。但是,如果我首先将对象作为参数传递给组件,然后以嵌套方式绑定表达式,则会出现错误

测试组件:

@using System.Linq.Expressions;
@using System.Reflection;


@code
{
    [Parameter]
    Expression<Func<string>> For { get; set; }

    protected override void OnInit()
    {  

        var propertyInfo = ((MemberExpression)For.Body).Member as PropertyInfo;

        var me = (MemberExpression)((MemberExpression)For.Body).Expression;
        var ce = (ConstantExpression)me.Expression;
        var fieldInfo = ce.Value.GetType().GetField(me.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        var thisObject = fieldInfo.GetValue(ce.Value);
    }

}

包装组件

@using Models

<TestComponent For="@(() => Obj.Name)"></TestComponent>

@code
{
    [Parameter]
    TestModel Obj { get; set; }
}

测试页

@page "/test"

<TestComponent For="@(() => obj.Name)"></TestComponent>
<WrapperComponent Obj="@obj"></WrapperComponent>

@code
{
    TestModel obj = new TestModel();
}

仅运行第一个组件 TestComponent 可以正常工作。如果我改为运行第二个组件 WrapperComponent,我会得到以下信息:

NullReferenceException: Object reference not set to an instance of an object.

    CustomerportalCore.Components.TestComponent.OnInit() in TestComponent.razor

            var thisObject = fieldInfo.GetValue(ce.Value);

Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.Renderer_UnhandledException(object sender, Exception e)
Microsoft.AspNetCore.Components.Browser.Rendering.RemoteRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.Rendering.Renderer.AddToPendingTasks(Task task)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterCollection parameters)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, int componentId, ArrayRange<RenderTreeFrame> oldTree, ArrayRange<RenderTreeFrame> newTree)
Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
Microsoft.AspNetCore.Components.Rendering.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
Microsoft.AspNetCore.Components.Rendering.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.Renderer_UnhandledException(object sender, Exception e)
Microsoft.AspNetCore.Components.Browser.Rendering.RemoteRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.Rendering.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.Rendering.Renderer.AddToRenderQueue(int componentId, RenderFragment renderFragment)
Microsoft.AspNetCore.Components.RenderHandle.Render(RenderFragment renderFragment)
Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.Renderer_UnhandledException(object sender, Exception e)
Microsoft.AspNetCore.Components.Browser.Rendering.RemoteRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.Rendering.Renderer.AddToPendingTasks(Task task)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterCollection parameters)
Microsoft.AspNetCore.Components.Rendering.Renderer.RenderRootComponentAsync(int componentId, ParameterCollection initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterCollection initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterCollection initialParameters)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost+<>c__DisplayClass41_0+<<PrerenderComponentAsync>b__0>d.MoveNext()
Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c__11<TResult>+<<InvokeAsync>b__11_0>d.MoveNext()
Microsoft.AspNetCore.Components.Server.Circuits.CircuitPrerenderer.PrerenderComponentAsync(ComponentPrerenderingContext prerenderingContext)
Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentPrerenderingExtensions.RenderComponentAsync<TComponent>(IHtmlHelper htmlHelper, object parameters)
CustomerportalCore.Pages.Pages__Host.<ExecuteAsync>b__22_1() in _Host.cshtml

            @(await Html.RenderComponentAsync<App>())</App>

Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
CustomerportalCore.Pages.Pages__Host.ExecuteAsync()
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我错过了什么?

4

1 回答 1

1

我不是 Blazor 的专家,但如果你调用表达式OnInit而不是反射,它似乎给了我一个明智的答案:

For.Compile().Invoke()

给我“测试,测试”,这就是我给我的模型作为Name. 这可能是一个可怕的建议,或者虽然内置了一些未知的恐怖 ¯(ツ)/¯

快速搜索表明,通过创建和评估大量表达式/函数可能存在一些内存问题,因此可能需要考虑

于 2019-07-17T06:56:55.937 回答