标签: onion-architecture

Unity:隐式ResolvedParameter用于未命名的注册

UserService构造函数有两个参数,一个是IUnitOfWorkIUserRepository:

public UserService(IUnitOfWork unitofWork, IUserRepository userRepository) 
{ ... }
Run Code Online (Sandbox Code Playgroud)

我使用命名注册来区分多个实例IUnitOfWork,因此在UserService使用Unity容器注册时,我需要使用以下命令显式指定参数InjectionConstructor:

container.RegisterType<IUserService, UserService>(
    new InjectionConstructor(
        new ResolvedParameter<IUnitOfWork>("someContext"),
        new ResolvedParameter<IUserRepository>()
    )
);
Run Code Online (Sandbox Code Playgroud)

有可能new ResolvedParameter<IUserRepository>()被省略吗?我希望Unity隐式推导出这个参数,因为不需要命名注册. 代码如下所示:

container.RegisterType<IUserService, UserService>(
    new InjectionConstructor(
        new ResolvedParameter<IUnitOfWork>("someContext")
    )
);
Run Code Online (Sandbox Code Playgroud)

当我不需要使用时,这将完成InjectionConstructor.

dependency-injection ioc-container inversion-of-control unity-container onion-architecture

6
推荐指数
1
解决办法
894
查看次数

具有 DI 与洋葱架构的分层架构?

任何人都可以使用依赖倒置来解释洋葱架构和分层架构之间的区别吗?他们在我看来完全一样。非常感谢任何输入:)

n-layer onion-architecture

5
推荐指数
1
解决办法
1108
查看次数

长期运行的、有状态的“服务”在 DDD 中适用于何处?

在更多与行业或自动化相关的应用程序(主要依赖于他们必须管理的外部组件)中,您经常会遇到这样的情况,即域包含的模型不仅仅是对实际问题的抽象,还包括表示和指向域外物理存在的事物的指针。

以这个代表网络设备的域实体为例:

public class NetworkDevice {
   public IPAddress IpAddress { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

应用程序可能需要根据它们在域内的表示来管理外部组件,而不是仅仅存储或验证此类实体或对实体更改采取行动。现在,DDD 甚至适合这种情况吗?那些经理是域服务吗?

Eric Evans 在他著名的蓝皮书中描述,域服务需要是一个无状态 模型,实现取自ubiquitos 语言的方法,以完成实体或存储库无法自行处理的请求。但是如果一个服务需要有状态呢?

一个简单的例子:一个应用程序需要监控网络配置的IP 设备,以便将状态事件通知域内的其他应用程序。如果 IP 设备在应用程序中注册(例如存储在数据库中),“ping-service”会收到通知并开始监视设备。

public class PingMonitor : IDisposable,
   IHandle<DeviceRegisteredEvent>,
   IHandle<DeviceRemovedEvent> 
{

    public List<NetworkDevice> _devices = new List<NetworkDevice>();

    public void Handle(DeviceRegisteredEvent @event) {
        _devices.Add(@event.Device);
    }

    public void Handle(DeviceRemovedEvent @event) {
        _devices.Remove(@event.Device);
    }

    public void PingWorker() {
        foreach(var device in _devices) {
            var status = Ping(device.IpAddress);
            if(status …
Run Code Online (Sandbox Code Playgroud)

c# design-patterns domain-driven-design cqrs onion-architecture

5
推荐指数
1
解决办法
1348
查看次数

异步处理领域事件

我已经按照Udi Dahan 的领域事件 - 救赎文章中的规定实现了领域事件。

据我了解,域事件可以异步运行到引发它的线程(通常来自域模型或服务)。

不需要任何类型的“共享”工作单元或存储库实现,也不需要事务一致性。

问:为什么 Udi 没有在单独的线程中实现领域事件的处理?

例如,我添加了 a 的创建Task来异步处理事件:

public static void Raise<T>(T domainEvent) where T : IDomainEvent
{
    if (Container != null)
    {
        foreach (var handler in Container.ResolveAll<IDomainEventHandler<T>>())
        {
            Task.Factory.StartNew(() => 
            { 
                handler.Handle(domainEvent); 
            }).ContinueWith(t => {
                // Log exception
            }, TaskContinuationOptions.OnlyOnFaulted);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由此可能产生任何多线程问题吗?

编辑: 请注意,虽然这些域事件是轻量级的,但它们仍将在 IIS 上运行,因为这是一个 MVC Web 项目。

multithreading domain-driven-design dependency-injection onion-architecture domain-events

5
推荐指数
0
解决办法
1450
查看次数

领域层的日志接口

我的域层中有一些非常昂贵的业务逻辑,必须在其中跟踪数据,以便了解发生故障时发生的情况。因此,我想声明一个简单的日志记录接口:

public interface ILogger {
    void Log(LogEntry entry);
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是 - 这个接口属于哪里?当然,日志记录可能是一个基础设施问题(还有一点跨层问题),但是如果我将它放在基础设施层,我的域服务就无法访问它。如果放到领域层,就引入了登录自己领域的概念,感觉很别扭。

我已经在我的应用程序中使用了 CQRS 和 EventSourcing 中的某些概念,但是为域服务中的数据发生的所有事情抛出一个事件似乎有点矫枉过正(尤其是如果数据处于无法返回的状态时)通过域服务,直到进行了进一步的转换。)

c# logging domain-driven-design onion-architecture

5
推荐指数
1
解决办法
1861
查看次数

如何在洋葱架构中使用来自 KendoUI 的 ToDataSourceResult 而不暴露 IQueryable

我正在设计具有 Onion 架构的应用程序,并且我想将 Kendo UI 中的网格与服务器端过滤排序和分页一起使用。我想避免手动将 DataSourceRequest 解析为动态 LinQ,而是使用 ToDataSourceResult。

我来到了工作解决方案,其中我的控制器包含以下内容:

    private ISalesService salesService;

    public HomeController(ISalesService salesService)
    {
        this.salesService = salesService;
    }

    public JsonResult Post([DataSourceRequest] DataSourceRequest request)
    {
        var sales = salesService.GetQueryableSales();

        return Json(sales , JsonRequestBehavior.AllowGet);

    } 
Run Code Online (Sandbox Code Playgroud)

ISalesService 映射到我使用存储库的实现,代码如下:

    public IQueryable<SalesOrderHeader> GetQueryableSales()
    {
        if (context == null) 
            context = new AdventureWorks2012Context();

        return context.SalesOrderHeaders;
    }
Run Code Online (Sandbox Code Playgroud)

这只是应用程序的一个骨架,因此在服务和存储库中都没有逻辑。这样我就可以避免手动解析 DataSourceRequest,但代价是将 IQueryable 暴露给 MVC 层。我想将 IQueryable 保留在存储库中,并在可能的情况下公开 IEnumerable,或者可能来自 Kendo UI 库的 DataSourceResult。

我尝试更改我的存储库调用如下:

    public DataSourceResult GetSales(DataSourceRequest request)
    {
        using (var c = new AdventureWorks2012Context())
        { …
Run Code Online (Sandbox Code Playgroud)

linq asp.net-mvc onion-architecture kendo-grid

5
推荐指数
1
解决办法
1420
查看次数

DDD结构示例

我正在尝试使用 DDD 和洋葱/六边形/干净架构(使用 Java 和 Spring)构建应用程序。我发现找到有关概念本身的指导比实际如何实施它们更容易。特别是 DDD 似乎很难找到有指导意义的例子,因为每个问题都是独一无二的。我在 SO 上看到了很多有用的例子,但我仍然有疑问。我想知道通过我的例子是否会帮助我和其他任何人。

我希望你能原谅我在这里问了不止一个问题。这个例子似乎太大了,我在多个问题中重复它没有意义。

语境:

我们有一个应用程序,它应该显示有关足球统计数据的信息,并具有以下概念(为简单起见,我没有包括所有属性):

  • 拥有众多球员的团队。
  • 球员。
  • 夹具,有 2 个团队和 2 个半场。
  • Half,其中有 2 个 FormationsPlayed 和许多组合。
  • FormationPlayed,其中有很多 PositionsPlayed。
  • PositionPlayed,它有 1 个玩家和一个位置值对象。
  • 组合,可以是2种类型,并且有很多Move。
  • Move 可以有 2 种类型,有 1 个 Player 和一个事件值对象。

可以想象,试图找出哪些事物是聚合根是很棘手的。

  • 团队可以独立存在,AR 也是如此。
  • Player 可以独立存在,AR 也是如此。
  • Fixture 在删除时也必须删除它的 Halves,AR 也是如此。
  • Half 必须是 Fixture 中的实体。
  • 删除一半时必须删除FormationPlayed,所以也许这应该是Half中的一个实体。
  • 当一个 Formation 被删除时,PositionPlayed 必须被删除,所以相信这应该是 FormationPlayed 中的一个实体。
  • 某种意义上的组合可以独立存在,尽管与特定的游戏半场相关。也许这可能是一个受最终一致性约束的 AR。
  • 当一个组合被删除时,移动必须被删除,所以相信这应该是组合中的一个实体。

问题:

  1. 你看到上面的设计有什么错误吗?如果是这样你会改变什么?
  2. Fixture - Half - FormationPlayed - PositionPlayed 聚合似乎太大,所以我想知道您是否同意可以使用最终一致性将其拆分为 Fixture - Half 和 FormationPlayed - PositionPlayed。我找不到一个例子是这是如何在 …

java domain-driven-design eventual-consistency onion-architecture

5
推荐指数
1
解决办法
2643
查看次数

休眠业务对象可以用作干净架构中的实体吗?

在我们的项目中,我们使用 eclipse hibernate 插件生成的类进行持久化。生成的类具有以下结构。

MyClass extends BaseMyClass //POJO's, that are refenced in the hbm
files
Run Code Online (Sandbox Code Playgroud)
MyClassDAO extends BaseMyClassDAO //DAO objects that use hibernate
session objects to provide CRUD API's for working with DB
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果我们使用映射文件中使用的 POJO 类作为最内层的实体,是否会违反 Uncle Bobs 的清洁架构。

在这种情况下,hibernate 特定的 DAO 类将属于最外层,而 UseCases 层将通过提供要实现的接口与该层进行通信。

java hibernate hexagonal-architecture onion-architecture clean-architecture

5
推荐指数
1
解决办法
528
查看次数

Onion架构中抛出异常与返回操作结果对象

我有一个由 Onion Architecture 实现的项目,它与Ordering类似。我需要处理所有层中的验证错误。据我所知,一般有以下两种方法来处理错误:

1-抛出异常

2-返回操作结果

在您看来,哪一个最好?

1-抛出异常

这是我的方法。正如您在ValidatorBehavior中看到的,我曾经像这样ValidatorBehavior处理与验证我的命令相关的验证错误。 FluentValidation用于验证输入命令,错误缓存在.HandleValidatorBehavior

问题之一是FluentValidation如果命令无效则抛出异常。此异常可以缓存在Web API 中的HttpGlobalExceptionFilter中。

有人说异常是针对意外情况的,但在这种情况下(验证),我们知道验证阶段的结果,并且我们通过抛出异常来实现一些业务规则。

另一种是使用抛出异常,Domain LayerStatusChangeException。所以毫无疑问,我们需要在其他层抛出异常。

2-返回操作结果

在我的一些朋友建议的第二种方法中,我们可以使用处理错误,通过名为的对象向最终用户显示这些错误OperationResult。从性能角度来看,它似乎更好,因为抛出异常比第一种方法更昂贵。

您对这两种方法有何看法?我想知道您是否分享您的想法以做出最佳决定。

c# architecture error-handling onion-architecture

5
推荐指数
1
解决办法
1531
查看次数

在洋葱、六边形或简洁架构中,域模型是否可以包含与数据库中的域模型不同的属性?

我问你谁知道并有使用任何分层架构(洋葱、六边形、干净等)构建软件的经验。每当我在谷歌上搜索软件架构时,人们都会有不同的观点,并以不同的方式解释相同的架构。

条款

在您阅读问题之前,有些术语可能会让您感到困惑,因此我将在下面对其进行定义。我不确定我是否对它们有“正确”的定义,但我从互联网上收集了这些信息。如果我有误解,请告诉我。

领域层:包含企业/业务逻辑并使用领域模型。位于中心并且不依赖于除领域模型之外的任何其他层。

应用层:包含应用逻辑,从基础设施层接受DTO,传递View Model

DTO(Data Transfer Object):用于在层与层之间传输数据的类、JSON字符串等。可能是一个纯数据容器。

VM(View Model):从应用层传递到表示层的DTO。

DO(Domain Model):域层使用的类、JSON字符串等。可能是一个纯数据容器。

VO(Value Object):数据库实体(一个数据库行),或者数据库使用的一种数据格式。可以从数据库层转移到应用层。

概括

在洋葱、六边形或简洁架构中,域层位于中心(即域层不依赖于域模型以外的任何层,域模型用于将数据传输到其他层或接受来自更高层的数据)。

这意味着域使用的域模型(DTO、POJO、VO 或其他)可能与数据库用于保存持久数据的模型不同。

我画了一个图表,以便我可以给你更好的解释。

在此处输入图片说明

在此处输入图片说明

第一季度

请看第二张图片的红色部分。

与传统的分层或 n 层架构不同,如果领域层位于中心,那么领域模型是否可以拥有比数据库实体(行)更多的属性(或不同的属性)?

例如,假设域层使用一个名为Person的类。用户请求所有在服务器中注册的人的照片。让我们假设数据库只包含所有人的姓名。但是,我们可能会使用其他网络服务器通过姓名请求某人的照片。所以应用层会从数据库中读取所有的名称,并通过这些名称,通过 HTTP 请求从其他 Web 服务器获取所有图片。之后,带有姓名和图片的Person列表将作为视图模型(DTO)发送给用户。

问题二

持久层可能由数据库、文件系统、其他 Web API 等组成。

表示层可以是网站、桌面应用、移动应用、Web API 等。

这两层都是基础设施层的一部分,都依赖于应用层,而应用层只依赖于领域层。

当应用层接受来自表现层的请求时,没有问题,因为表现层调用应用层,表现层知道应用层。

大多数时候,应用层需要从持久层获取数据。

应用层无法在没有任何依赖的情况下调用持久层,因为它不知道持久层中的任何类。

这就是我目前的理解,谁能给我一个清晰的解释,数据应该如何流动以及从低层到高层的通信是如何完成的?

对于那些想写代码的人,我更喜欢 C#。

software-design n-tier-architecture hexagonal-architecture onion-architecture clean-architecture

5
推荐指数
1
解决办法
1352
查看次数