我最近成为了Autofac的OwnedInstances功能的重要用户。例如,我用它来提供一个工厂来为我的数据库创建一个工作单元,这意味着我依赖于UnitOfWork工厂的类要求输入类型的对象:
Func<Owned<IUnitOfWork>>
这非常有用 - 非常适合keeping IDisposable out of my interfaces - 但它带有价格:自拥有&lt;&gt;是Autofac程序集的一部分,我必须在每个知道Owned&lt;&gt;的项目中引用Autofac,并在每个代码文件中放置“使用Autofac.Features.OwnedInstances”。
函数功能&LT;&GT;具有内置于.NET框架的巨大好处,因此我毫不怀疑将Func用作通用工厂包装器是可以的。但是拥有&lt;&gt;在Autofac程序集中,每次我使用它时,我都会创建一个对Autofac的硬引用(即使我在接口方法参数中对Autofac的唯一引用是Owned&lt;&gt;类型)。
我的问题是:这是件坏事吗?这会开始以某种方式让我回头,我还没有考虑到这一点吗?有时我会有一个由许多其他项目引用的项目,因此我自然需要将其依赖关系尽可能接近零;我通过传递Func&lt; Owned&lt; IUnitOfWork&gt;&gt;做恶(这实际上是一个数据库事务提供者)进入这些接口中的方法(否则将是autofacnnostic)?
也许如果拥有&lt;&gt;是一个内置的.NET类型,这整个困境会消失吗? (我是否应该屏住呼吸才能实现?)
答案 0 :(得分:11)
我同意@steinar,我会认为Autofac是另一个支持您项目的第三方dll。您的系统依赖于它,为什么要限制自己参考它?如果在您的代码周围散布ILifetimeScope
或IComponentContext
,我会更加关注。
那就是说,我感受到了你的安慰。毕竟,DI容器应该在幕后工作,而不是“溢出”到代码中。但是我们可以轻松地创建一个包装器和一个界面来隐藏Owned<T>
。请考虑以下界面和实现:
public interface IOwned<out T> : IDisposable
{
T Value { get; }
}
public class OwnedWrapper<T> : Disposable, IOwned<T>
{
private readonly Owned<T> _ownedValue;
public OwnedWrapper(Owned<T> ownedValue)
{
_ownedValue = ownedValue;
}
public T Value { get { return _ownedValue.Value; } }
protected override void Dispose(bool disposing)
{
if (disposing)
_ownedValue.Dispose();
}
}
可以使用注册源或构建者进行注册,例如像这样:
var cb = new ContainerBuilder();
cb.RegisterGeneric(typeof (OwnedWrapper<>)).As(typeof (IOwned<>)).ExternallyOwned();
cb.RegisterType<SomeService>();
var c = cb.Build();
您现在可以照常解决:
using (var myOwned = c.Resolve<IOwned<SomeService>>())
{
var service = myOwned.Value;
}
您可以将此界面放在系统中的公共命名空间中,以便于包含。
Owned<T>
和OwnedWrapper<T>
现在都隐藏在您的代码中,只显示IOwned<T>
。如果需求发生变化,您需要将Autofac替换为另一个DI容器,那么这种方法的摩擦力就会大大降低。
答案 1 :(得分:10)
我想说,在“企业应用程序”解决方案(或任何需要灵活性的应用程序)的每个项目中引用一组定义明确的核心第三方DLL都没关系。我认为在每个需要它的项目中至少依赖以下内容没有错:
这些不是核心.NET框架的一部分这一事实不应该阻止我们自由地使用它们。
与可能的好处相比,我能看到的唯一可能的负面影响相对较小:
答案 2 :(得分:3)
也许如果拥有&lt;&gt;是一个内置的.NET 类型,这整个进退两难的局面 远? (我应该屏住呼吸 要发生这种情况?)
它将成为内置的.NET类型:ExportLifeTimeContext<T>
。尽管有这个名字,但这个类并没有真正绑定到.NET ExportFactory<T>
。构造函数只接受一个值,并在释放该值的生命周期时调用Action
。
目前,它仅适用于Silverlight。对于常规.NET框架,您必须等到.NET 4.x(或4.0之后的下一个版本)。
答案 3 :(得分:3)
我不认为引用Autofac程序集是真正的问题 - 我认为应用程序代码中出现Owned
之类的问题&#39;代码气味&#39;。应用程序代码不应该关心正在使用的DI框架,并且在代码中使用Owned
现在会对Autofac产生硬依赖。所有与DI相关的代码都应该干净地包含在一组配置类中(Autofac世界中的模块)。