可能的GetObjectsOfType替换

我有这小段代码

var idObjects = Spring.Context.Support.ContextRegistry.GetContext() .GetObjectsOfType(typeof (ICustomInterfaceThatDoesSomething)); foreach (ICustomInterfaceThatDoesSomething icitds in idObjects.Values) icitds.DoSomething(); 

有没有办法可以避免这种情况,让spring.net自动将单例注入我声明的属性,就像一个ICustomInterfaceThatDoesSomething数组?

我想要这样的事情的唯一原因是因为我想杀死项目的.dll依赖项,这是单一的使用点。

您还可以使用方法注入 :

在sharedLib中:

 public class MyService { public void ProcessAll() { foreach (ICustomInterfaceThatDoesSomething icitds in GetAllImplementers()) icitds.DoSomething(); } protected virtual IEnumerable GetAllImplementers() { // note that the Spring dependency is gone // you can also make this method abstract, // or create a more useful default implementation return new List(); } } 

在Web应用程序中添加一个实现GetAllImplementers()

 public class ServiceLocatorImplementer : IMethodReplacer { protected IEnumerable GetAllImplementers() { var idObjects = Spring.Context.Support.ContextRegistry.GetContext() .GetObjectsOfType(typeof(ICustomInterfaceThatDoesSomething)); return idObjects.Values.Cast(); } public object Implement(object target, MethodInfo method, object[] arguments) { return GetAllImplementers(); } } 

并在Web应用程序的对象定义中配置方法注入:

        

我觉得使用CommonServiceLocator会更好(因为服务位置就是你正在做的事情),但是这样使用方法注入,你不需要引入对SharedLib的额外引用。

您问题的有趣部分是:如何在库中使用服务定位器函数(例如spring.net的IApplicationContext.GetObjectsOfType(...) ),而不会引入对特定IoC容器的依赖。

如问题中所述,这很有用,因为我们希望构建不强制使用者使用特定IoC容器的库。 但是,我们仍然希望使用IoC容器,因为它简化了库的开发。 Jeremy Miller在“IoC Container Detente的时间”这篇文章中很好地描述了这种困境。

他的博客文章导致了一个名为CommonServiceLocator的小型项目 。 该项目为服务定位指定了一个IServiceLocator接口 ,该接口由许多流行的IoC容器实现,包括Spring.NET。

IServiceLocator定义IEnumerable GetAllInstances(); 方法,基本上是你问题中要求的方法。

当您的库需要服务定位器function时,您可以依赖CommonServiceLocator库,您和其他消费者可以使用您选择的IoC容器连接它。

并猜测:Spring.NET适配器实现IEnumerable GetAllInstances(); 使用GetObjectsOfType(serviceType);

我会在这里留下这个答案以供将来参考,但我更喜欢我的其他答案 。

最初的答案相当长,并且对问题中的例子非常具体。

我认为没有相当于GetObjectsOfType(...)的配置。

但是,摆脱Spring.net依赖是不是很容易?

让我看看我是否理解正确:

 // sharedLib contains ICustomInterfaceThatDoesSomething // by "-->" I mean "depends on" webApp --> Spring.Core, Spring.Web webApp --> sharedLib sharedLib --> Spring.Core // only to call GetObjectsOfType(...) on Spring container 

我们希望摆脱最后的依赖关系,因为我们希望能够将sharedLib与另一个DI容器结合使用。 在sharedLib我们有一个类需要发出所有ICustomInterfaceThatDoesSomething实现的信号来执行某些操作。 为此,我创建:

 MySomethingManager { public MySomethingManager() {} public MySomethingManager(IMySomethingDoerProvider prov) { // init SomethingDoers } IList SomethingDoers { get; set; } void SignalAllToDoSomething() { foreach (var doer in Provider.SomethingDoers ) doer.DoSomething(); } } IMySomethingDoerProvider { IList GetAll(); } 

MySomethingManager用于包含Spring依赖项,但现在它是Spring Free。 现在,我在关于MySomethingManager连接sharedLib时有两个选项:

  1. MySomethingManager.SomethingDoers上使用属性注入与List
  2. 使用IMySomethingDoerProvider实现的构造函数注入

两者都可以使用Spring和许多其他DI容器完成。 如果您不介意在配置中列出所有ICustomInterfaceThatDoesSomething ,则可以使用第一种方法。

如果您需要神奇的GetObjectsOfType(...)代码,则可以使用DI容器的function来创建IMySomethingDoerProvider

使用Spring时,第二种方法需要创建:

 MySomethingDoerSpringProvider: IMySomethingDoerProvider { IList GetAll() { // use Spring.Context.Support.ContextRegistry.GetContext() // .GetObjectsOfType(typeof (ICustomInterfaceThatDoesSomething)); } } 

您可以将其放置在依赖于sharedLib的项目中。 由于您的webApp已经依赖于Spring.Core,因此您可以将MyProvider放在那里以便快速入门。

笔记

如果每个实例调用一次DoSomething ,您可以考虑指定一个初始化方法。

感谢Marijin的洞察力已经被钉死了!

首先考虑这个通用实用程序类

 public class ServiceLocatorImplementer : IMethodReplacer { private readonly Type _forType; public ServiceLocatorImplementer(Type forType) { this._forType = forType; } protected IEnumerable GetAllImplementers() { var idObjects = Spring.Context.Support.ContextRegistry.GetContext() .GetObjectsOfType(_forType); return idObjects.Values; } public object Implement(object target, MethodInfo method, object[] arguments) { return GetAllImplementers(); } } 

使用此配置示例声明它

              

最后注入所需的目标

这种方法的GetAllICheImplentations()是,在你实际执行GetAllICheImplentations()之前不会调用底层的GetObjectsOfType(除非你试图在spring init期间执行它,这不会很好)