我正在使用AutoMapper将Entity映射到ViewModel。 该实体的一个属性是datetime。 我想使用TimeZone将该日期时间转换为本地日期时间。 TimeZone存储在用户的会话对象中。 我已经有了ISessionManager ,可以从用户的会话中检索信息。 我不知道如何将此ISessionManager注入AutoMapper

在下面的代码中,如何将ISessionManager.CurrentTimeZone属性传递给FromUTCToLocal()方法?

    public class SessionManager:ISessionManager
    {
       public TimeZoneInfo CurrentTimeZone
       {
          return (TimeZoneInfo)Session["CurrentTimeZone"];
       }
    }


    public static class DateTimeExtenstions
    {
        public static DateTime FromLocalToUTC(this DateTime dateTime, TimeZoneInfo timeZone)
        {
            // Here instead of taking timeZone as parameter i can
            // use servicelocator to get instance of ISessionManager
            // like var timeZone = ServiceLocator.GetInstance<ISessionManager>()
            // However i don't want to use servicelocator pattern since
            // everywhere else i am using IOC
            // also it doesnt make sense to use ServiceLocator inside extension method

            return TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone);
        }        
    }

    public class AutoMapperConfig
    {
        public static IMapper Config()
        {
            var config = new MapperConfiguration(cfg =>
            {
                //Create all maps here               
                cfg.CreateMap<MyEntity, MyViewModel>()
                    .ForMember(vm => vm.CreatedDateTime,
                            y => y.MapFrom(entity => entity.CreatedOn.FromUTCToLocal()))
            });

            return config.CreateMapper();
        }
    }   


    public static class UnityConfig
    {
        public static void RegisterComponents(IMapper mapper)
        {
            var container = new UnityContainer();

            container.RegisterType<ISessionManager, SessionManager>(new HierarchicalLifetimeManager());

            container.RegisterInstance(mapper);            

            UnityServiceLocator locator = new UnityServiceLocator(container);
            ServiceLocator.SetLocatorProvider(() => locator);
        }
    }

   public class MvcApplication : System.Web.HttpApplication
   {
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        UnityConfig.RegisterComponents(AutoMapperConfig.Config());                
    }
   }

===============>>#1 票数:5

我认为这是一种反模式,因为mappers应该是愚蠢的,因此你可能想要抵制在其中加入过多逻辑的诱惑。 查询数据是您的域实现的责任,但是如果您在没有它的情况下进行管理(特别是在扩展方法内),那么您是否正确使用ServiceLocator。

也许您应该丰富您映射的域对象,而不是在映射过程中尝试添加缺少的信息(TimeZoneInfo)。

===============>>#2 票数:0

AutoMapper实际上并不是一个反模式,它实际上是为了处理你想要的,你只需要采取不同的方法(奇怪的是我解决了这个问题,同时也解决了我最初尝试解决方案的UTC问题基于扩展方法)。

您不需要使用扩展方法,而是使用AutoMapper的ValueResolvers。 根据这是否是特定于某个特定类的映射,或者它是某个特定数据类型的一般映射,您需要实现IValueResolver(对于前者)或IMemberValueResolver(对于后者)。

这是一个很好的资源,可以帮助你完成大部分工作: https//github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers

没有解决的问题是注入旋转变压器。

一个例子是这样的:

public class DateTimeUtcResolver : IMemberValueResolver<object, object, DateTime, DateTime>
{
    ISessionManager sessionManager;

    public DateTimeUtcResolver(ISessionManager sessionManager)
    {
        this.sessionManager = sessionManager;
    }

    public DateTime Resolve(object source, object destination, DateTime sourceMember, DateTime destinationMember, ResolutionContext context)
    {
        //logic
    }
}

你的映射器会有这样的东西:

cfg.CreateMap<MyEntity, MyViewModel>()
    .ForMember(vm => vm.CreatedDateTime,
               y => y.ResolveUsing<DateTimeUtcResolver, DateTime>(entity => entity.CreatedOn))

从那里只记得用AutoMapper注册你的IOC容器,这样就可以确定ISessionManager的实现。 这本身可能很棘手,但取决于你正在使用什么类型的容器(这个帮助了我很多,ymmv:Automapper 并请求特定资源

  ask by LP13 translate from so

未解决问题?本站智能推荐: