我最近成为 Autofac 的 OwnedInstances 功能的重度用户。例如,我使用它来提供一个工厂来为我的数据库创建工作单元,这意味着依赖于工作单元工厂的类需要类型为 的对象:
Func<Owned<IUnitOfWork>>
这非常有用 - 非常适合 将 IDisposable 排除在我的界面之外- -但它是有代价的:自从拥有>>是 Autofac 程序集的一部分,我必须在每个了解 Owned<> 的项目中引用 Autofac,并将“using Autofac.Features.OwnedInstances”放入每个代码文件中。
函数<>内置于 .NET 框架中的巨大好处,因此我毫不怀疑使用 Func 作为通用工厂包装器是可以的。但拥有<>位于 Autofac 程序集中,每次使用它时,我都会创建对 Autofac 的硬引用(即使我对 Autofac 的唯一引用是接口方法参数中的 Owned<> 类型)。
我的问题是:这是一件坏事吗?这是否会以某种我尚未考虑到的方式开始反噬我?有时我会有一个被许多其他项目引用的项目,所以自然地我需要保持它的依赖关系尽可能接近零;我是否通过传递 Func> 来作恶? (实际上是一个数据库事务提供者)到这些接口中的方法(否则将与 autofac 无关)?
也许如果拥有<>如果是内置的 .NET 类型,那么整个困境就会消失吗? (我什至应该屏住呼吸才能发生这种情况吗?)
I've recently become a heavy user of Autofac's OwnedInstances feature. For example, I use it to provide a factory for creating a Unit of Work for my database, which means my classes which depend on the UnitOfWork factory are asking for objects of type :
Func<Owned<IUnitOfWork>>
This is incredibly useful--great for keeping IDisposable out of my interfaces--but it comes with a price: since Owned<> is part of the Autofac assembly, I have to reference Autofac in each of my projects that knows about Owned<>, and put "using Autofac.Features.OwnedInstances" in every code file.
Func<> has the great benefit of being built into the .NET framework, so I have no doubts that it's fine to use Func as a universal factory wrapper. But Owned<> is in the Autofac assembly, and every time I use it I'm creating a hard reference to Autofac (even when my only reference to Autofac is an Owned<> type in an interface method argument).
My question is: is this a bad thing? Will this start to bite me back in some way that I'm not yet taking into account? Sometimes I'll have a project which is referenced by many other projects, and so naturally I need to keep its dependencies as close as possible to zero; am I doing evil by passing a Func<Owned<IUnitOfWork>> (which is effectively a database transaction provider) into methods in these interfaces (which would otherwise be autofac-agnostic)?
Perhaps if Owned<> was a built-in .NET type, this whole dilemma would go away? (Should I even hold my breath for that to happen?)
发布评论
评论(4)
我同意 @steinar,我将 Autofac 视为另一个支持您的项目的第 3 方 dll。您的系统依赖于它,为什么您应该限制自己引用它?如果
ILifetimeScope
或IComponentContext
散布在您的代码中,我会更加担心。话虽如此,我感受到了你的担忧。毕竟,DI 容器应该在幕后工作,而不是“溢出”到代码中。但我们可以轻松创建一个包装器和一个接口来隐藏
Owned
。考虑以下接口和实现:可以使用注册源或构建器来完成注册,例如:
您现在可以照常解析:
您可以将此接口放置在系统中的公共命名空间中以便于包含。
Owned
和OwnedWrapper
现在都对您的代码隐藏,仅公开IOwned
。如果需求发生变化并且您需要将 Autofac 替换为另一个 DI 容器,则这种方法的摩擦会少很多。I agree with @steinar, I would consider Autofac as yet another 3rd party dll that supports your project. Your system depends on it, why should you restrict yourself from referencing it? I would be more conserned if
ILifetimeScope
orIComponentContext
were sprinkled around your code.That said, I feel your consern. After all, a DI container should work behind the scenes and not "spill" into the code. But we could easily create a wrapper and an interface to hide even the
Owned<T>
. Consider the following interface and implementation:The registration could be done, either using a registration source or a builder, e.g. like this:
You can now resolve as usual:
You could place this interface in a common namespace in your system for easy inclusion.
Both the
Owned<T>
andOwnedWrapper<T>
are now hidden from your code, onlyIOwned<T>
is exposed. Should requirements change and you need to replace Autofac with another DI container there's a lot less friction with this approach.我想说,在“企业应用程序”解决方案(或任何需要灵活性的应用程序)的每个项目中引用一组明确定义的核心第 3 方 DLL 是很好的。我认为在每个需要它的项目中至少依赖以下内容没有什么问题:
事实上,这些不是核心 .NET 框架的一部分。不要阻止我们随意使用它们。
与可能的好处相比,我能看到的唯一可能的负面影响相对较小:
I would say that it's fine to reference a well defined set of core 3rd party DLLs in every project of an "enterprise application" solution (or any application that needs flexibility). I see nothing wrong with having a dependency on at least the following in every project that needs it:
The fact that these aren't part of the core .NET framework shouldn't stop us from using them as liberally.
The only possible negatives I can see are relatively minor compared to the possible benefits:
它将成为内置的 .NET 类型:
ExportLifeTimeContext
。尽管有这个名称,此类实际上并未绑定到 .NETExportFactory
。构造函数只接受一个值和一个在该值的生命周期被释放时调用的Action
。目前,它仅在 Silverlight 中可用。对于常规 .NET 框架,您必须等到 .NET 4.x(或 4.0 之后的下一个版本)。
It will become a built-in .NET type:
ExportLifeTimeContext<T>
. Despite the name, this class isn't really bound to the .NETExportFactory<T>
. The constructor simply takes a value, and anAction
to invoke when the lifetime of that value is disposed.For now, it is only available in Silverlight though. For the regular .NET framework you'll have to wait until .NET 4.x (or whatever the next version after 4.0 will be).
我不认为引用 Autofac 程序集是真正的问题 - 我认为应用程序代码中出现的诸如
Owned
之类的内容是“代码味道”。应用程序代码不应该关心正在使用什么 DI 框架,并且代码中的Owned
现在会创建对 Autofac 的硬依赖。所有 DI 相关代码都应该干净地包含在一组配置类(Autofac 世界中的模块)中。I don't think referencing the Autofac assembly is the real problem - I consider things like
Owned
appearing in application code a 'code smell'. Application code shouldn't care about what DI framework is being used and havingOwned
in your code now creates a hard dependency on Autofac. All DI related code should be cleanly contained in a set of configuration classes (Modules in the Autofac world).