在AutoMapper使用上下文值投影(Projection using contextual va

2019-08-19 01:41发布

我目前的评估AutoMapper是否有利于我们的项目。 我正在使用的ASP.NET Web API一个REST的Web API,和的事情,我必须返回一个包含链接的资源。 考虑该简化示例中,使用以下的域对象:

public class Customer
{
    public string Name { get; set; }
}

我需要把这个映射到一个资源对象,有点像一个DTO但添加的属性,以方便REST。 这就是我的资源对象可能是这样的:

public class CustomerResource
{
    public string Name { get; set; }
    public Dictionary<string, string> Links { get; set; }
}

链接属性将需要包含相关资源的链接。 现在,我可以使用下面的方法构建它们:

public IEnumerable<CustomerResource> Get()
{
    Func<Customer, CustomerResource> map = customer => 
        new CustomerResource
        {
            Name = customer.Name,
            Links = new Dictionary<string, string>()
            {
                {"self", Url.Link("DefaultApi", new { controller = "Customers", name = customer.Name })}
            }
        }

    var customers = Repository.GetAll();
    return customers.Select(map);
}

...但是这是非常繁琐的,我有很多的嵌套的资源,这样的。 我看到的问题是,我不能使用AutoMapper,因为它不会让我提供范围限定到执行映射操作的点投影过程中所需的某些事情。 在这种情况下,ApiController的URL属性提供UrlHelper情况下,我需要创建链接给我,但可能还有其他案件。

你将如何解决这个难题?

PS我输入了这个代码专门针对这个问题,它在你的头编译,但在你喜欢的IDE可能会失败。

Answer 1:

这是不是一个漂亮的解决方案,而是通过文档看完之后似乎没有一个......目前,我们在情境的东西被扔映射Tuple<TDomainType, TContextStuff>TDataTransfer 。 所以你的情况你最好Mapper.CreateMap<Tuple<Customer, Controller>, CustomerResource>

不漂亮,但它的作品。



Answer 2:

我想看看在使用一个自定义类型转换 。 该类型的转换器可以有通过IOC容器注入的上下文信息。 或者,由于转换器在配置时实例化,它可能有一个工厂,将各类型转换器运行时返回上下文信息的参考。

简单的例子

你可以定义为让你当前的“上下文”的界面(这意味着什么取决于你在做什么,如何实现这样的事情在这个例子中我就当前的HttpContext它可以让你访问会话,服务器,邮件,等等...):

public interface IContextFactory
{
    HttpContext GetContext();
}

和实现很简单:

public class WebContextFactory : IContextFactory
{
    public HttpContext GetContext()
    {
        return HttpContext.Current;
    }
}

您的自定义类型转换可能需要IContextFactory的实例,从您的IOC容器和每个映射运行时,你可以调用的getContext()来获得当前请求的上下文。

访问URL属性

该UrlHelper来自附加到当前的控制器的情况下请求对象。 不幸的是,这是不是在HttpContext的可用。 但是,您可以覆盖你的ApiController初始化方法和存储HttpContext.Items集合在controllerContext:

protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
    HttpContext.Current.Items["controllerContext"] = controllerContext;
    base.Initialize(controllerContext);
}

然后,您可以访问从当前HttpContext:

var helper = ((HttpControllerContext) HttpContext.Current.Items["controllerContext"]).Request.GetUrlHelper();

我不知道这是最好的解决办法,但它可以让你自定义类型映射器内UrlHelper实例。



文章来源: Projection using contextual values in AutoMapper