问题描述
我目前的评估AutoMapper是否能有利于我们的项目。我正在使用的ASP.NET Web API一个REST的Web API,以及事情我必须返回一个是包含链接的资源。考虑这个简单的例子,使用下面的域对象:
I'm currently evaluation whether AutoMapper can be of benefit to our project. I'm working on a RESTful Web API using ASP.NET Web API, and one of the things I must return is a resource that contains links. Consider this simplified example, using the following domain object:
public class Customer
{
public string Name { get; set; }
}
我需要把这个映射到一个资源对象,有点像DTO但随着添加的属性,以方便REST。这是我的资源对象可能看起来是这样的:
I need to map this into a resource object, sort of like a DTO but with added properties to facilitate REST. This is what my resource object may look like:
public class CustomerResource
{
public string Name { get; set; }
public Dictionary<string, string> Links { get; set; }
}
的链接属性将需要包含相关资源的链接。现在,我可以构建他们使用下面的方法:
The Links property will need to contain links to related resources. Right now, I could construct them using the following approach:
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实例,我需要创建链接的我,但可能还有其他案件。
...but this is pretty tedious and I have a lot of nested resources and such. The problem that I see is that I can't use AutoMapper because it doesn't let me provide certain things needed during projection that are scoped to the point where the mapping operation is performed. In this case, the Url property of the ApiController provides the UrlHelper instance that I need to create the links for me, but there may be other cases.
你会如何解决这个难题?
How would you solve this conundrum?
PS我专门输入了验证码这个问题,它在你的头编译,但在你喜欢的IDE可能会失败。
P.S. I typed up this code specifically for this question, and it compiled in your head but may fail in your favorite IDE.
推荐答案
我看起来中使用。类型转换器可能通过IOC容器注入的上下文信息。或者,由于转换器在配置的时候实例化,它可能有一个工厂,将各类型转换器运行时返回上下文信息的参考。
I would look in to using a Custom Type Converter. The type converter could have contextual information injected via an IOC container. Or, since the converter is instantiated at configuration time, it could have a reference to a factory which would return contextual information each time the type converter is run.
简单的例子
您可以定义一个接口让你的当前的背景(这意味着什么取决于你在做什么,以及如何实现这样的事情在这个例子中我就当前的HttpContext它可以让你访问会话,服务器,邮件等):
You could define an interface for getting your current "context" (what that means depends on what you're doing and how you implement things so for this example I'll just the current HttpContext which gets you access to Session, Server, Items, etc...):
public interface IContextFactory
{
HttpContext GetContext();
}
和实施很简单:
public class WebContextFactory : IContextFactory
{
public HttpContext GetContext()
{
return HttpContext.Current;
}
}
您自定义类型转换可能需要IContextFactory的实例,从您的IOC容器,每个映射运行时,你可以调用的getContext()来获得当前请求的上下文。
Your custom type converter could take an instance of IContextFactory from your IOC container and each time the mapping is run, you can call GetContext() to get the context for the current request.
访问的URL属性强>
的UrlHelper来自连接到电流控制器的上下文请求对象。不幸的是,这不是在HttpContext的提供。但是,您可以覆盖你的ApiController初始化方法和存储controllerContext HttpContext.Items集合中:
The UrlHelper comes from the Request object attached to the current controller's context. Unfortunately, that is not available in the HttpContext. However, you could override the Initialize method on your ApiController and store the controllerContext in the HttpContext.Items collection:
protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
HttpContext.Current.Items["controllerContext"] = controllerContext;
base.Initialize(controllerContext);
}
您就可以访问,从目前的HttpContext:
You can then access that from the current HttpContext:
var helper = ((HttpControllerContext) HttpContext.Current.Items["controllerContext"]).Request.GetUrlHelper();
我不知道它的的最的解决方案,但它可以得到您的自定义类型映射器里面的UrlHelper实例。
I'm not sure it's the best solution, but it can get you the UrlHelper instance inside your custom type mapper.
这篇关于在AutoMapper使用上下文值投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!