Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Blazor应用程序中,分离关注点和单一责任原则的最佳实践是什么?_Blazor_Blazor Server Side_Solid Principles_Asp.net Blazor_Blazor Webassembly - Fatal编程技术网

在Blazor应用程序中,分离关注点和单一责任原则的最佳实践是什么?

在Blazor应用程序中,分离关注点和单一责任原则的最佳实践是什么?,blazor,blazor-server-side,solid-principles,asp.net-blazor,blazor-webassembly,Blazor,Blazor Server Side,Solid Principles,Asp.net Blazor,Blazor Webassembly,我使用的是从ComponentBase派生的base继承的Razor文件。我的理解是,这两个文件通常应该负责处理与UI相关的任务。也就是说,我是否应该将对数据服务的调用放在低级组件中?或者我应该将对它们的调用保留在一个更高级别的组件中,该组件可以协调数据服务,然后简单地将数据传递给组件以处理呈现?(当我提到高级别或低级别时,我的意思是父组件将是高级别,子组件将是低级别) 据我所知,为处理数据服务而注入的接口将包含相同的资源(作为单例)。所以我的问题不是关于资源的管理,而是关于保持稳定。数据服务应

我使用的是从ComponentBase派生的base继承的Razor文件。我的理解是,这两个文件通常应该负责处理与UI相关的任务。也就是说,我是否应该将对数据服务的调用放在低级组件中?或者我应该将对它们的调用保留在一个更高级别的组件中,该组件可以协调数据服务,然后简单地将数据传递给组件以处理呈现?(当我提到高级别或低级别时,我的意思是父组件将是高级别,子组件将是低级别)


据我所知,为处理数据服务而注入的接口将包含相同的资源(作为单例)。所以我的问题不是关于资源的管理,而是关于保持稳定。数据服务应该在哪里使用?无处不在还是与世隔绝?谢谢

我将作为一名大力支持将服务隔离到基类的人加入进来。在得出这个结论之前,我一直遇到的一个问题是,随着应用程序规模和复杂性的增加,将服务调用分散到任何地方都会让人感到困惑。将每个组件构建为一个原子组件是很有诱惑力的,它可以自己处理所有事情并注入服务,但一旦所有这些组件开始组合在一起并需要开始相互通信,这就成为一个巨大的难题。当您有任何状态都可能涉及的单例时,这种情况就会发生,因为组件的底层状态很容易被另一个组件更改。(有时不是故意的-请参阅EF Core和数据跟踪,以及从2个组件引用被跟踪数据时的乐趣-或者更糟的是,Blazor服务器上的2个独立客户端连接)在您知道之前,有太多的地方可以查找错误或在需要更改时进行更改,追踪虫子就成了噩梦

实现组件自治的第二个途径是使用级联参数,但无论何时,都要将组件耦合到DOM树上某个具体的组件上,避免耦合才是最重要的。通常最好让每个组件都代表非常简单的功能,可以组合起来为用户创造更丰富的体验

因此,我发现成功的地方在于隔离您在基类中提到的服务,然后使DOM树中的每个组件尽可能保持沉默,这对我的输出以及我查找和修复错误的能力产生了巨大的影响。事实上,我有一个项目,在我开始这种方法之前,我不得不放弃两次,现在我在一个功能性应用程序中,以一个好的剪辑构建特性。(谢天谢地,这是一个爱好项目!)

这种方法一点也不复杂。在基类中,我将在需要时将方法调用和属性公开为受保护的,并尽可能保持所有其他内容的私有性,因此外部可见性是绝对最小的。所有服务调用也发生在基类中,并封装在私有方法中,这会中断服务和UI之间的连接。然后,我将数据作为组件参数向下传递DOM树,并将功能作为
EventCallback
类型的参数向下传递

以经典的订单列表为例。我可以按客户ID加载订单列表,然后通过使用expression bodied成员筛选主列表,简单地公开打开的订单列表和关闭的订单列表。所有这些都发生在基类中,但我对它进行了设置,以便UI能够访问的只有子列表和方法。在下面的示例中,我通过控制台日志表示服务调用,但您会明白,您在问题中提到的构建基本上是这样的:

OrdersBase.cs

公共类OrdersBase:ComponentBase
{
私有列表_orders=新列表();
受保护的列表OpenOrders=>\u orders.Where(o=>o.IsClosed==false.ToList();
受保护的列表关闭程序=>\u orders.Where(o=>o.IsClosed==true.ToList();
受保护的无效关闭订单(订单)
{
_orders.Find(o=>o.Id==order.Id).IsClosed=true;
WriteLine($”服务被调用以关闭订单#{order.Id});
}
受保护的无效OpenOrder(订单)
{
_orders.Find(o=>o.Id==order.Id).IsClosed=false;
WriteLine($“调用服务打开订单#{order.Id}”);
}
受保护的重写异步任务OnInitializedAsync()
{
Console.WriteLine(“呼叫服务为客户填写订单列表#1…”);
//几个订单的快速模型
_订单=新列表()
{
新订单(){Id=1,OrderName=“订单号1”,CustomerId=1},
新订单(){Id=2,OrderName=“订单号2”,CustomerId=1},
新订单(){Id=3,OrderName=“订单号3”,CustomerId=1},
新订单(){Id=4,OrderName=“订单号4”,CustomerId=1},
新订单(){Id=5,OrderName=“订单号5”,CustomerId=1},
};
Console.WriteLine(“已填写订单列表”);
}
}
现在我可以使用顶级组件中的基类,并且只能访问受保护和公共成员。我可以使用这个高级组件来编排UI的排列方式,并为代理传递方法,这就是它所要做的。这是非常轻的结果

订单。剃须刀

@page”/orders
@继承OrdersBase
未结订单:
未结订单:
然后,OrderList组件负责呈现OrderItems列表并传递委托操作。同样,这只是一个简单、愚蠢的组件

OrderList.razor