【问题标题】:With an onion architecture should all lower layer objects be used through an interface?对于洋葱架构,是否应该通过接口使用所有较低层的对象?
【发布时间】:2015-03-24 00:05:07
【问题描述】:

我对洋葱架构有点陌生。我创建了一个服务层,它通过手动将 DAL 中的存储库传递给构造函数来调用它们。但是现在看看我的方法,我正在使用来自核心域的对象,我想知道我是否应该传入一个接口来访问它?是否应该通过通过参数、构造函数、属性等传入的接口访问所有对象?我知道这会减少耦合,但就最佳实践而言,这意味着什么?

在我的代码中,我想知道是否

DiaryEvent diaryEvent = new DiaryEvent();

应该用作接口而不是具体对象。附言DiaryEvent 来自下面的层(核心)。

public class DiaryEventService : IDiaryEventService
{
    private readonly IYogaSpaceEventRepository yogaSpaceEventRepository;

    public DiaryEventService() : this(new YogaSpaceEventRepository())
    {

    }

    public DiaryEventService(IYogaSpaceEventRepository yogaSpaceEventRepository)
    {
        this.yogaSpaceEventRepository = yogaSpaceEventRepository;
    }

    public  List<DiaryEvent> LoadAllAppointmentsInDateRange(double start, double end)
    {
        var fromDate = ConvertFromUnixTimestamp(start);
        var toDate = ConvertFromUnixTimestamp(end);

        var yogaSpaceEvents = yogaSpaceEventRepository.Find(fromDate, toDate);

        List<DiaryEvent> result = new List<DiaryEvent>();

        foreach (var item in yogaSpaceEvents)
        {
            DiaryEvent diaryEvent = new DiaryEvent();
            diaryEvent.ID = item.YogaSpaceEventId;
            //diaryEvent.SomeImportantKeyID = item.SomeImportantKey;
            diaryEvent.StartDateString = item.DateTimeScheduled.ToString("s");
            // "s" is a preset format that outputs as: "2009-02-27T12:12:22"
            diaryEvent.EndDateString = item.DateTimeScheduled.AddMinutes(item.AppointmentLength).ToString("s");
            // field AppointmentLength is in minutes
            diaryEvent.Title = item.Title + " - " + item.AppointmentLength.ToString() + " mins";
            diaryEvent.StatusString = Enums.GetName<AppointmentStatus>((AppointmentStatus)item.StatusEnum);
            diaryEvent.StatusColor = Enums.GetEnumDescription<AppointmentStatus>(diaryEvent.StatusString);
            string ColorCode = diaryEvent.StatusColor.Substring(0, diaryEvent.StatusColor.IndexOf(":"));
            diaryEvent.ClassName = diaryEvent.StatusColor.Substring(diaryEvent.StatusColor.IndexOf(":") + 1,
                diaryEvent.StatusColor.Length - ColorCode.Length - 1);
            diaryEvent.StatusColor = ColorCode;
            result.Add(diaryEvent);
        }

        return result;
    }

    private static DateTime ConvertFromUnixTimestamp(double timestamp)
    {
        var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return origin.AddSeconds(timestamp);
    }
}

【问题讨论】:

标签: c# asp.net-mvc dependency-injection decoupling onion-architecture


【解决方案1】:

但是现在看看我的方法,我正在使用来自核心域的对象 我想知道我是否应该传入一个接口来访问它 也一样?

看看你上面的代码,看起来你做对了。 DiaryEvent 看起来像一个结构,即没有行为的数据对象,因此无需将其替换为接口。接口输出对象有助于在运行时和此处注入它们,因为您没有调用任何行为,即 DiaryEvent 的方法,可以直接将它们实例化到方法中。

是否所有对象都应该通过正在通过的接口访问 参数、构造函数、属性等??

不,不是真的。这样想,如果您从类中调用方法,则该类将依赖于被调用方法/类的行为。为了使其松散耦合,即在运行时更改行为/模拟它,您需要注入此依赖项。要从外部注入依赖项,您需要接口或抽象依赖项。

验证您的类是否松散耦合的一个好方法是为其方法模拟依赖项编写一个单元测试用例。

【讨论】:

  • 只是一个简单的问题。我正在使用洋葱架构,所以我的域类中不应该有任何方法,对吧?所有业务逻辑都包含在核心的外层中?你建议我的类中可能有方法。
  • 当你说域类时,你的意思是实体,即数据库表?如果是,那么对您的第一个问题的回答是肯定的,您的实体类中不应该有任何方法。它只是一个数据持有者,代表 DB 中的一行 DB 表。业务逻辑将包含在一个单独的层中,获取实体(有时称为模型对象)并应用业务逻辑。业务或服务层经常返回模型对象。在表示层,您将它们转换为 ViewModel 对象,然后再将其交给查看。
猜你喜欢
  • 2015-03-17
  • 1970-01-01
  • 2011-10-09
  • 2013-06-30
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
相关资源
最近更新 更多