nin*_*eff 6 .net closures dependency-injection castle-windsor ioc-container
我一直在尝试使用命名委托而不是单方法接口.这对代码的大小一定的优势,因为我们可以从(一些换行符删除,以免夸大的情况下)去:
public interface IProductSource
{
IEnumerable<Product> GetProducts();
}
public class DataContextProductSource : IProductSource
{
private readonly DataContext _DataContext;
public DataContextProductSource(DataContext dataContext)
{
if (dataContext == null) throw new ArgumentNullException("dataContext");
_DataContext = dataContext;
}
public IEnumerable<Product> GetProducts()
{
return _DataContext.Products.AsEnumerable();
}
}
Run Code Online (Sandbox Code Playgroud)
至:
public delegate IEnumerable<Product> DGetProducts();
public static class DataContextFunctions
{
public DGetProducts GetProducts(DataContext dataContext)
{
if (dataContext == null) throw new ArgumentNullException("dataContext");
return () => dataContext.Products.AsEnumerable();
}
}
Run Code Online (Sandbox Code Playgroud)
这基本上利用了这样一个事实:一旦你使用依赖注入足够远,很多类变得只是闭包.这些类可以用返回lambdas的函数替换.整套相关函数(不需要封装任何可变状态,但在"标准"依赖注入中使用类表示)可以汇总到静态类(或VB术语中的"模块") .
这一切都很好,但我找不到使用Castle Windsor注册这些静态方法的最佳方法.没有依赖关系的方法很简单:
Component.For<DGetIntegers>().Instance(Integers.GetOneToTen)
Run Code Online (Sandbox Code Playgroud)
但是我们上面的DataContextFunctions.GetProducts有一些依赖关系.我发现注册这个的最好方法是:
Component.For<DGetProducts>().UsingFactoryMethod(
kernel => DataContextFunctions.GetProducts(kernel.Resolve<DataContext>())
Run Code Online (Sandbox Code Playgroud)
这可能会变得非常冗长,显然不得不直接询问内核的每一个依赖类型.在我看来,容器应该需要的所有静态信息都是可用的,因此应该可以这样做.
问题是,Castle Windsor(或任何其他容器)是否有一种简单的方法可以做到这一点,我已经错过了,或者是否存在技术问题,或者它是否只是包含在一个用例中?
Mar*_*ann 10
简短的回答
你试图让DI容器(Castle Windsor)执行功能组合,但它实际上是针对对象组合的.这只会给你带来很多摩擦.我的猜测是你将获得与其他容器相同的体验.
DI容器是围绕面向对象的概念设计的 - 特别是SOLID.它们与这些原理配合得非常好,因为它们的设计具有构造函数注入和自动布线等内在的理解.
更实用的方法没有任何问题,但我还没有看到围绕功能组合而不是对象组合构建的DI容器.
答案很长
由于几个原因,使用委托作为DI的一般原则往往在静态类型语言(至少在.NET中)中存在问题.从概念上讲,这种方法没有任何问题,因为委托可以被视为匿名角色接口.但是,由于类型模糊,它往往变得笨拙.
我通常看到的最常见的方法是使用BCL的内置代理,例如Func<T>,Action<T>等等.但是,您可能有许多不同的消费者依赖Func<string>于哪种情况变得模棱两可 - 仅仅因为消费者需要一个Func<string>并不意味着他们需要代理人担任同一个角色.虽然机械上可能会将DI与代理一起使用,但会发生的情况是委托隐藏应用程序角色.角色消失,只剩下机械师.
然后,您可以按照OP中的建议为每个角色定义自定义委托,如此委托所建议的那样:
public delegate IEnumerable<Product> DGetProducts();
Run Code Online (Sandbox Code Playgroud)
但是,如果你采取这种方式,那么什么都得不到.仍必须为每个角色定义"角色委托".相比之下,定义一个类似的界面,应该清楚,唯一的保存是几个尖括号和一个显式的方法定义:
public interface IProductSource { IEnumerable<Product> GetProducts(); }
Run Code Online (Sandbox Code Playgroud)
这不是很多开销(如果有的话).
您可能还想看一下这个讨论:http://thorstenlorenz.wordpress.com/2011/07/23/dependency-injection-is-dead-long-live-verbs/
| 归档时间: |
|
| 查看次数: |
705 次 |
| 最近记录: |