在AutoMapper中使用上下文值进行投影

我目前正在评估AutoMapper是否对我们的项目有利。 我正在使用ASP.NET Web API处理RESTful 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; }
}

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

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中失败。


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

不漂亮,但它的作品。


我会着眼于使用自定义类型转换器。 类型转换器可以通过IOC容器注入上下文信息。 或者,由于转换器在配置时被实例化,所以它可以具有对每次运行类型转换器时都会返回上下文信息的工厂的引用。

简单的例子

你可以定义一个接口来获得当前的“上下文”(这意味着你要做什么以及如何实现,所以对于这个例子我只需要当前的HttpContext,它可以访问Session,Server,Items,等等...):

public interface IContextFactory
{
    HttpContext GetContext();
}

实现很简单:

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

您的自定义类型转换器可以从IOC容器中获取IContextFactory的实例,并且每次运行映射时,都可以调用GetContext()获取当前请求的上下文。

访问Url属性

UrlHelper来自附加到当前控制器上下文的Request对象。 不幸的是,这在HttpContext中不可用。 但是,您可以重写ApiController上的Initialize方法,并将controllerContext存储在HttpContext.Items集合中:

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实例。

链接地址: http://www.djcxy.com/p/70471.html

上一篇: Projection using contextual values in AutoMapper

下一篇: Use RACCommand with Asynchronous Network Operation