Autofac 属性注入
我正在更改我的 Asp.Net MVC3 项目以使用 Autofac 将服务注入到我的控制器中。到目前为止,这非常简单。我的服务都有一个 Telerik OpenAccess db 属性,我通过构造函数注入该属性(在服务基类中)。我的控制器都具有也被注入的服务的构造函数属性。
我有一个名为 AuditInfo 的类,它封装了控制器的可审核属性:
public class AuditInfo
{
public string RemoteAddress { get; set; }
public string XForwardedFor { get; set; }
public Guid UserId { get; set; }
public string UserName { get; set; }
}
我的服务类中的 OpenAccess db 属性需要注入此类的实例,以便在各种数据库调用中用作审核信息。
问题是,这不是一个可以在Application_Start 处实例化的类,因为它的至少两个属性RemoteAddress 和XForwardedFor 在OnActionExecuting 的最早阶段(即一旦Request 变量存在)就被填充。
因此,我在 BaseController 类的 OnActionExecuting 方法中实例化它,如下所示:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
db.AuditInfo = AuditInfo;
}
public AuditInfo AuditInfo
{
get
{
return new AuditInfo()
{
RemoteAddress = this.Request.ServerVariables["REMOTE_ADDR"],
XForwardedFor = this.Request.ServerVariables["X_FORWARDED_FOR"],
UserId = this.UserId,
UserName = this.UserName
};
}
}
所以 - 我的问题是:
- 我不喜欢直接访问 OnActionExecuting 中的 OpenAccess db 属性。
- 我希望将此 AuditInfo 基本上注入到任何
- 我不认为可以使用 AuditInfo 的构造函数注入的任何 AuditInfo 属性中,因为服务依赖于数据库 - 控制器依赖于服务 - 数据库依赖于 AuditInfo 但 AuditInfo 在以下情况之前不可用控制器被实例化并收到第一个请求。 =>循环依赖...
我将如何设置 autofac 将 AuditInfo 注入到任何将其作为属性的类中?或者是否有更好的方法来回避循环依赖并使用某种形式的 lambda/惰性构造函数属性?
即使许多请求可能是同一会话的一部分并且没有不同的 IP 地址/用户信息,但 AuditInfo 在每次请求时都可能不必要地重新初始化,这是否值得关注?
谢谢
I am in the process of changing my Asp.Net MVC3 project to use Autofac for service injection into my controllers. So far this has been pretty straightforward. My services all have a Telerik OpenAccess db property which I inject through the constructors (In a service base class). And my controllers all have constructor properties for services which also get injected.
I have a class called AuditInfo which encapsulates auditable properties of a controller:
public class AuditInfo
{
public string RemoteAddress { get; set; }
public string XForwardedFor { get; set; }
public Guid UserId { get; set; }
public string UserName { get; set; }
}
My OpenAccess db property in my service classes needs to have an instance of this class injected in to it in order to use as auditing information in various database calls.
The problem is that this is not a class that can be instantiated at Application_Start because at least two properties of it, RemoteAddress and XForwardedFor are populated at the earliest stage of OnActionExecuting, i.e. once the Request variables exist.
Therefore, I instantiate this in the OnActionExecuting method of my BaseController class as such:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
db.AuditInfo = AuditInfo;
}
public AuditInfo AuditInfo
{
get
{
return new AuditInfo()
{
RemoteAddress = this.Request.ServerVariables["REMOTE_ADDR"],
XForwardedFor = this.Request.ServerVariables["X_FORWARDED_FOR"],
UserId = this.UserId,
UserName = this.UserName
};
}
}
So - my problem/questions are:
- I don't like this direct reach in to the OpenAccess db property in OnActionExecuting.
- I'd like this AuditInfo basically to be injected in to any AuditInfo property anywhere
- I don't think I can use constructor injection for AuditInfo because Services depend on db - controllers depend on services - db depends on AuditInfo BUT AuditInfo is not available until a controller is instantiated and received its first request. => circular dependency...
How would I setup autofac to inject AuditInfo in to any class that has it as a property? Or is there a better way of sidestepping the circular dependency and using some form of lambda/lazy constructor properties?
Is it at all concerning that AuditInfo gets re-initialized potentially unnecessarily at every request even though a lot of requests may be part of the same session and not have different ip address/user info?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
事实证明,Autofac 的 MVC 集成可以解析
HttpRequestBase
你。因此您不需要直接引用HttpContext.Current.Request
。Autofac 的实现使用
HttpContext.Current
在幕后。这是有效的,因为 MVC 框架在您的代码(或 Autofac 的)运行之前设置HttpContext.Current
。因此不存在循环依赖 - 请求“自然存在”在HttpContext.Current.Request
上,就像在控制器中一样。 (这个问题解释了如何进行)因此,您可以按照 Steven 的建议创建一个 IAuditInfoFactory,但在其构造函数中要求一个 HttpRequestBase,而不是使用 HttpContext.Current(如果这能让您感觉更好)不是引用静态变量。
此外,不存在循环依赖,如果需要,您可以通过构造函数注入
AuditInfo
:It turns out Autofac's MVC Integration can resolve an
HttpRequestBase
for you. So you don't need to referenceHttpContext.Current.Request
directly.Autofac's implementation uses
HttpContext.Current
behind the scenes. This works because the MVC framework setsHttpContext.Current
before your code (or Autofac's) runs. So there's no circular dependency - the Request "naturally exists" onHttpContext.Current.Request
just as much as in your controller. (This question kind of explains how)So you could do an
IAuditInfoFactory
as Steven suggests but demand anHttpRequestBase
in its constructor instead of usingHttpContext.Current
if it makes you feel better about not referencing static variables.Also, there's no circular dependency and you could constructor-inject the
AuditInfo
if you want:答案是:使用工厂。
将
IAuditInfoFactory
注入到需要它的类型中,并创建一个如下所示的实现:您可以按如下方式注册该类:
现在您可以注入
The answer is: Use a factory.
Inject an
IAuditInfoFactory
into the type that needs it, and create an implementation like this:You can register that class as follows:
Now you can inject