gpt4 book ai didi

c# - 如何向域实体注入(inject)服务以及如何持久化实体

转载 作者:行者123 更新时间:2023-12-04 07:54:34 25 4
gpt4 key购买 nike

我正在创建一个旅游规划器。 Tour 始终在同一坐标开始和结束。在开始和结束之间,有 Stop。停靠站包含一个特定的景点,可以在旅游期间和参观时间参观。在游览中添加景点时,我插入了一个新的停靠点,并根据停靠点之间的距离重新计算停靠点的到达时间。为此,我在 private recalculateStopTimes(int fromIdx) 方法中使用了注入(inject)的 ITravelService 实例。


我的问题如下:在我想通过 ORM 将 Tour 对象保存在数据库中之前,这一直有效。由于私有(private) ITravelService,该功能将在检索后丢失。我考虑过通过 InsertSight/RemoveSight/RemoveStop 方法注入(inject)服务,但随后我需要用我创建的每个修改 Stops 的公共(public)方法注入(inject)它。有没有更好的方法将这样的服务注入(inject)实体?或者我什至应该注入(inject)它?如果不是,我如何获得相同的功能(重新计算它的停靠点)?

public interface ITravelService
{
public TimeSpan CalculateTimeBetween(Coordinates from, Coordinates to);
}

public class Tour : ITour
{
private readonly List<Stop> _stops;
private ITravelService _travelService;

public IReadOnlyList<Stop> Stops { get { return _stops; } }
public bool IsWithinLimit { get { return _stops.Last().TimeRange.From < (StartTime.TimeOfDay + Length); } }


public Tour(DateTime startTime, TimeSpan length, Coordinates start, ITravelService travelService)
{
StartTime = startTime;
Length = length;
Stop firstStop = new Stop(start, new TimeRange(startTime.TimeOfDay, startTime.TimeOfDay));
Stop lastStop = new Stop(start, new TimeRange(startTime.TimeOfDay, startTime.TimeOfDay));
_stops = new List<Stop>() { firstStop, lastStop };
}

private void recalculateStopTimes(int fromIdx)
{
for (int i = fromIdx; i < _stops.Count - 1; i++)
{
Stop currentStop = _stops[i];
Stop nextStop = _stops[i + 1];
var travelTime = _travelService.CalculateTimeBetween(currentStop.Coordinates, nextStop.Coordinates);
nextStop.Arrival = currentStop.TimeRange.To + travelTime;
}
}

public void InsertSight(Sight sight, int index)
{
if (index == 0 || index == Stops.Count) throw new ArgumentOutOfRangeException("Cannot insert before first, or after last stop.");
_stops.Insert(index, new SightStop(sight, StartTime.DayOfWeek));

recalculateStopTimes(index - 1);
}

public void RemoveSight(Sight sightToRemove)
{
if (_stops.Count == 2) throw new ArgumentException("Sight is not in tour");
int idx = 1;
while (((_stops[idx] as SightStop).Sight != sightToRemove) && idx <= _stops.Count - 1)
{
idx++;
}
if (idx < _stops.Count)
{
RemoveStopAt(idx);
}
else
{
throw new ArgumentException("Sight is not in tour");
}
}

public void RemoveStopAt(int index)
{
if (index > 0 && index < _stops.Count - 1)
{
_stops.RemoveAt(index);
recalculateStopTimes(index - 1);
}
else
{
throw new ArgumentOutOfRangeException("Index was out of range");
}
}

public IReadOnlyList<Sight> SightsInTour
{
get
{
return _stops.Where(stop => stop is SightStop).Select(x => (x as SightStop).Sight).ToList();
}
}
}

最佳答案

如果您想坚持业务逻辑驻留在域实体内部的 DDD 方法,答案是应用 Method Injection :

// ITravelService is injected into the public InsertSight method
public void InsertSight(Sight sight, int index, ITravelService travelService)
{
...
}

Method Injection 注入(inject)是理想的,因为构造具有运行时数据和依赖项的对象(使用构造函数注入(inject))会导致 all kinds of trouble .相反,使用方法注入(inject)时,消费类 Tour使用依赖项,但从不存储任何字段中的依赖项。

提示:

  • 如果您需要其他私有(private)方法中的依赖项,请将依赖项从一个方法传递到另一个方法
  • 如果您的域方法需要很多依赖项,您将遇到类似于 constructor over-injection 的问题。 .构造函数过度注入(inject)是由一个类做的太多造成的。对于方法过度注入(inject),该方法做的太多了。有许多重构和设计技术可以用来解决这个问题,例如 Facade Service refactoring ,或类似 Domain Events 的设计,这是领域驱动设计的一个非常强大的部分。

关于c# - 如何向域实体注入(inject)服务以及如何持久化实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66768519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com