qkp*_*qkp 1 asp.net-mvc dependency-injection castle-windsor castle service-locator
我正在使用CastleWindsor作为我的依赖注入框架,当你在Controller中时它们都运行良好,因为我们可以使用controllerfactory构造函数注入.
但是有一些特定的情况,依赖注入(构造函数注入)将不起作用.例如:我希望能够在我的视图中的一些实用程序类或扩展方法(例如HtmlHelper)中使用IOC来解析依赖关系.我知道有些人不同意这一点,而是保持观点愚蠢,但让我们继续讨论.
所以这基本上让我有一个选项,那就是使用...服务定位器.所以我知道服务定位器被大多数人认为是反模式,我明白为什么..但是如果不能使用依赖注入,如何解决与IOC的依赖关系?对于我所知道的一切,使用IOC的服务定位器比没有任何东西更好.我想避免服务定位器模式,但我似乎不明白在某些特定情况下如何避免它.
接下来的问题是..所以即使你喜欢/不喜欢服务定位器.哪个是使用CastleWindsor实现此功能的最佳选择?
所以我猜选项是:
将容器公开为全局对象(或通过包装容器的其他全局对象),您可以从代码中的任何位置检索该容器.然后,您可以在容器上调用resolve和release方法.我不喜欢的一点是,我们必须明确地为瞬态生活方式对象调用release.如果没有经验的开发人员不这样做,你最终会发生内存泄漏.
我还发现:https://www.nuget.org/packages/CommonServiceLocator.WindsorAdapter,它有很多下载..(与选项1相同,但更通用,包装容器,以便您可以轻松交换DI框架)我查看了代码,发现适配器只有解析对象的方法.所以我有点想知道为什么没有发布方法..这是否意味着这个包有瞬态生活方式对象的内存泄漏问题?
希望有人能就这些问题给我一些建议!
如何避免在静态扩展方法(HTML Helpers)中使用服务定位器?
首先,尽可能避免使用静态扩展方法.当你有一些不太可能改变但没有依赖关系的逻辑(除了它们适用的类/接口之外)时,静态扩展方法很有效.当然,这并不总是可行,但如果您可以使用其他方法,它确实会减少这种情况.
2017/01/30更新:使用DI与HTML帮助程序的更好方法是使用抽象工厂,如本答案所示,它允许对HTML帮助程序依赖项进行DI容器生命周期管理.
当您确实需要使用静态方法时,注入依赖项的一种方法是使用属性注入.
public static class MyHtmlHelperExtensions
{
private static IHtmlHelperService htmlHelperService;
// Property for use with dependency injection in the composition root
public static IHtmlHelperService HtmlHelperService
{
set
{
if (value == null)
throw new ArgumentNullException("value");
if (htmlHelperService != null)
throw new ArgumentExeption("HtmlHelperService cannot be set twice");
htmlHelperService = value;
}
}
// The static method simply calls the instance method of our service,
// but does not contain any logic.
public static MvcHtmlString MyHtmlHelper(this HtmlHelper htmlHelper)
{
return htmlHelperService.MyHtmlHelper(htmlHelper);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,静态HTML帮助程序只是一个Facade,它将其方法委托给包含执行实际工作的实际服务的Aggregate Service.
将HtmlHelperService在应用程序启动时注入的DI容器建成刚过,但仍在内部组成根的应用程序.
// DIConfig.Register() will create the container and register all of our type mappings.
var container = DIConfig.Register();
// While we are still in the composition root, we instantiate and
// assign our HtmlHelperService along with its dependency graph.
MyHtmlHelperExtensions.HtmlHelperService = container.Resolve<IHtmlHelperService>();
Run Code Online (Sandbox Code Playgroud)
注意:在MVC6中,将存在视图组件,它们更像控制器而非静态HTML帮助程序,以消除创建具有依赖项的静态HTML帮助程序的需要.
至于Attributes导致服务定位器的依赖注入问题的另一个常见来源,最好的方法是定义没有行为的属性,可以通过将ActionFilterAttribute派生类型拆分为"哑"属性和DI友好全局来完成.在合成根中解析的动作过滤器.请参阅此MVC IActionFilter示例和此MVC AuthorizeAttribute示例.
没有理由认为属性需要定义行为,因为属性只定义可以由另一个服务(具有行为)探索的元数据.因此,属性永远不需要依赖项,只需要包含行为的服务.
| 归档时间: |
|
| 查看次数: |
736 次 |
| 最近记录: |