在微服务中创建域模型和视图模型的正确方法

时间:2018-12-13 22:40:46

标签: c# .net architecture .net-core microservices

我正在尝试创建微服务,并试图确保遵循最佳实践/模式来设计对象。

我计划分离对象,以便有一个用于返回(使用dapper进行查询)给客户端的对象(下面的类代码),而有一个实际上进行状态更改(此问题中的代码除外)的对象,该更改将提交对db的更改

我在数据库中有一个实体 CalendarEvents ,我有一个名为CalendarEvent的视图模型,它具有用于映射的每个实体字段的基本属性,还有许多其他属性CalendarEvent属性是实体字段的集合。

问题

  1. 如果从从db中读取的实体创建对象时,所有属性都应通过构造函数传递,那么填充此CalendarEvent对象(视图模型)的正确方法是什么?

  2. p>
  3. 我应该采用_dateformat还是有更优雅的方法(这来自配置文件)

下面是我的CalendarEntity类(用作视图模型的类)

如果有人能用我的方法发现任何其他问题(可能有很多),我将不胜感激。

public class CalendarEvent
{
    private readonly string _dateFormat;
    public CalendarEvent(string dateFormat)
    {
        _dateFormat = dateFormat;
    }

    public int EventId { get; set; }

    public string Title { get; set; }

    public DateTime? StartDateTimeUtc { get; set; }

    public DateTime? EndDateTimeUtc { get; set; }

    public string Summary { get; set; }

    public bool IsApproved { get; set; }

    public string TimeZoneId { get; set; }

    public bool IsDeleted { get; set; }

    public int ViewCount { get; set; }

    public DateTime CreatedDateUtc { get; set; }

    public DateTime? FeaturedStartDateUtc { get; set; }

    public DateTime? FeaturedEndDateUtc { get; set; }

    public string ContactEmailAddress { get; set; }

    public EventDateType DateType { get; set; }

    public int? Year { get; set; }

    public int? Period { get; set; }


    public EventCategory Category { get; set; }

    public string UrlFriendlyTitle => Helper.UrlFriendly(Title);

    public DateTime? EndDateTimeLocal { get; set; }

    public DateTime? StartDateTimeLocal { get; set; }

    public string FullEventDateString
    {
        get
        {
            string dateString;
            switch (DateType)
            {
                case EventDateType.Month:
                    {
                        var monthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(Period.Value);
                        dateString = $"{monthName} {Year}";
                        break;

                    }
                case EventDateType.Quarter:
                    {
                        dateString = $"{Period}{Helper.GetNumberOrdinalSuffix(Period.Value)} Quarter {Year}";
                        break;
                    }
                case EventDateType.Specific:
                    {
                        if (StartDateTimeLocal.HasValue && EndDateTimeLocal.HasValue)
                        {
                            if (StartDateTimeLocal.Value.Date == EndDateTimeLocal.Value.Date)
                            {
                                if (StartDateTimeLocal.Value.Date == EndDateTimeLocal.Value.Date
                                    && StartDateTimeLocal.Value.Hour == 0 && StartDateTimeLocal.Value.Minute == 0 &&
                                    StartDateTimeLocal.Value.Second == 0 && EndDateTimeLocal.Value.Hour == 23)
                                {
                                    dateString = StartDateTimeLocal.Value.ToString(_dateFormat);
                                }
                                else
                                {

                                    var eventDateTime =
                                        $"{StartDateTimeLocal.Value.ToString(_dateFormat)} {StartDateTimeLocal.Value.ToShortTimeString()} - {EndDateTimeLocal.Value.ToShortTimeString()}";
                                    dateString = eventDateTime;
                                }
                            }
                            else
                            {
                                var eventDateTime =
                                    $"{StartDateTimeLocal.Value.ToString(_dateFormat)} - {EndDateTimeLocal.Value.ToString(_dateFormat)}";

                                dateString = eventDateTime;
                            }


                            break;

                        }
                        //TODO: fix this
                        throw new NotImplementedException();

                    }
                default:
                    throw new ArgumentOutOfRangeException();
            }


            return dateString;
        }
    }

    public EventStatuses Status
    {
        get
        {
            if (IsDeleted)
            {
                return EventStatuses.Deleted;
            }
            if (StartDateTimeUtc > DateTime.UtcNow)
            {
                return EventStatuses.NotStarted;
            }
            if (StartDateTimeUtc <= DateTime.UtcNow && EndDateTimeUtc > DateTime.UtcNow)
            {
                return EventStatuses.InProgress;
            }
            return EventStatuses.Completed;
        }
    }

    public string UrlFriendlyTitleForDisplay
    {
        get
        {
            var textInfo = new CultureInfo("en-US", false).TextInfo;
            return textInfo.ToTitleCase(UrlFriendlyTitle.ToLower().Replace("-", " "));

        }
    }

    private void GenerateLocalTimes()
    {

        if (DateType == EventDateType.Specific && StartDateTimeUtc.HasValue && EndDateTimeUtc.HasValue)
        {

            var tz = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneId);

             //TODO: make sure ticks is zero in this case, this use to be totalSeconds comparison
            if (tz.BaseUtcOffset.Ticks == 0)
            {
                EndDateTimeLocal = EndDateTimeUtc;
                StartDateTimeLocal = StartDateTimeUtc;
            }
            else
            {
                EndDateTimeLocal = TimeZoneInfo.ConvertTimeFromUtc(EndDateTimeUtc.Value, tz);
                StartDateTimeLocal = TimeZoneInfo.ConvertTimeFromUtc(StartDateTimeUtc.Value, tz);
            }
        }
        else
        {

            //TODO: fix this
            throw new NotImplementedException();
        }
    }

    public string GoogleCalendarLink
    {
        get
        {
            if (DateType == EventDateType.Specific && StartDateTimeUtc.HasValue && EndDateTimeUtc.HasValue)
            {
                var text = string.Empty;
                if (!string.IsNullOrEmpty(Title))
                {
                    text = Uri.EscapeUriString(Title);
                }

                var startDate = StartDateTimeUtc.Value.ToString("yyyyMMddTHHmmssZ");
                var endDate = EndDateTimeUtc.Value.ToString("yyyyMMddTHHmmssZ");
                var details = string.Empty;
                if (!string.IsNullOrEmpty(Summary))
                {
                    details = Uri.EscapeUriString(Summary);
                }

                return
                    $"http://www.google.com/calendar/event?action=TEMPLATE&text={text}&dates={startDate}/{endDate}&details={details}&location=";
            }

            //TODO: fix this
            throw new NotImplementedException();

        }
    }
}

1 个答案:

答案 0 :(得分:0)

我将假设您正在使用Web Api,但相同的原理也适用于MVC应用程序。我通常有一个接受域对象的映射器层,并将其映射到视图模型或dto。这样,您可以在想要返回相同视图模型的任何时间重用映射器。因此,如果对视图模型进行了更改,则所有这些更改都位于一个位置。

请参见下面的代码来回答问题1。

问题2:您的微服务为什么要关心客户想要的日期。如果您发回utc日期,那么如果客户希望使用utc日期格式,则由他们自行格式化。

disabled

Folder structure