ServiceContainer、海洋学委员会和一次性对象
-
05-09-2019 - |
题
我有一个问题,我要签这个 主观的 因为我是这么认为它演变成,更多的讨论。我希望对于一些很好的想法或作一些思考-provokers.很抱歉我长篇大论的问题,但你需要知道的上下文。
这个问题基本上是:
- 你怎么处理具体类型的关系IoC容器?具体而言,谁是负责处理它们,如果它们需要处置,以及如何,知识得到传播出去呼叫密码?
你要求他们IDisposable?如果没有,是这一代面向未来,或者是规则,不能使用一次性对象?如果强制执行IDisposable-要求在接和具体类型的未来-的证据,其责任是对象注作为一部分的构造的电话?
编辑:我接受的答案 @克里斯*巴拉德 由于这是最近的一个方法我们结束了。
基本上,我们总是返回的一种类型,看起来是这样的:
public interface IService<T> : IDisposable
where T: class
{
T Instance { get; }
Boolean Success { get; }
String FailureMessage { get; } // in case Success=false
}
我们然后返回一个对象执行这一口回。解决。TryResolve,使我们得到的调用代码的总是相同的类型。
现在,对象执行这一接口, IService<T>
是IDisposable,并应 总是 以处置。这不是到编程员可以解决一个服务来决定是否 IService<T>
对象应该被设置或没有。
然而,这是至关重要的一部分,该业务是否实例应当设置或没有,这些知识融入的目的落实 IService<T>
, 所以如果它是一家工厂范围内的服务(ie。每个调决心结束了与新的服务实例),则服务实例将设置时 IService<T>
目的是设置的。
这也使得它能够支持其他特殊的范围,像池。我们现在可以说,我们想要至少2服务的实例、最大值15,并且通常5,这意味着每次呼叫。解决,无论检索服务实例,从一个游泳池的提供对象,或者建造一个新的一个。然后,当时的 IService<T>
目的,持有该汇集的服务设置的,服务的实例被释放回到游泳池。
当然,这使所有的代码这样的:
using (var service = ServiceContainer.Global.Resolve<ISomeService>())
{
service.Instance.DoSomething();
}
但这是一个干净的做法,和它具有相同的语法的类型无关的业务或具体目中使用,所以我们选择了这样一个可接受的解决方案。
原来的问题如下,为子孙后代
冗长的问题来了这里:
我们有一个IoC容器,我们使用,并且最近我们发现了什么数额的问题。
在非IoC代码,当我们想到使用,也就是说,一个文件,我们使用的一类是这样的:
using (Stream stream = new FileStream(...))
{
...
}
毫无疑问,是否有此类的东西,保持一个资源有限或者没有,因为我们知道,文件必须关闭,以及类本身实施IDisposable.规则很简单,就是每一类中,我们建造一个目的,即实现IDisposable,有待处置。没有问题要问。它没有达到用户的这类决定,如果调处理是可选择或没有。
好吧,那么上来的第一步,国际奥委会的容器中。让我们假设,我们不想代码直接对话的文件,但不是通过一个间接层.让我们叫这类BinaryDataProvider为这个例子。在国内,这类使用流,这仍然是一个一次性的目的,所以上述码将改为:
using (BinaryDataProvider provider = new BinaryDataProvider(...))
{
...
}
这没有太大变化。知识这类实现IDisposable还在这里,没有任何问题,我们需要呼吁处置。
但是,让我们假设,我们有课程,提供数据,现在不使用任何这样的有限的资源。
上述代码然后可以写为:
BinaryDataProvider provider = new BinaryDataProvider();
...
OK,so far so good,但是来这里的肉类的问题。让我们假设,我们想到使用IoC容器中注入这个供应商,而不是取决于一个特定的具体类型。
代码,然后将:
IBinaryDataProvider provider =
ServiceContainer.Global.Resolve<IBinaryDataProvider>();
...
注意,我假定存在独立接口可用,我们可以访问的目的通过。
与上述变化,如果我们晚上要用的对象真的应该加以处置?没有任何现有代码,可解决该接口是书面处置的对象,现在怎么样?
我们看到它,我们必须挑选一个解决办法:
- 执行运行检查,检查,如果一个具体的类型正在注册实现IDisposable,要求该接口,它是通过暴露也实现了IDisposable.这不是一个很好的解决方案
- Enfore约束的接口正在使用的,他们必须总是继承自IDisposable,以便能向未来
- 强制执行运行时,没有具体类型可IDisposable,由于这是具体处理不通过代码使用国际奥委会的容器
- 只是把它留给程序检查,如果对象实现IDisposable和"做正确的事"?
- 有没有其他人吗?
此外,什么有关注射对象在构造?我们的容器,而其他一些集装箱我们已经看到的,是能够注入新鲜的对象为一个参数的一个构造的一个具体的类型。例如,如果我们的 BinaryDataProvider
需要一个对象,实现了 ILogging
接口,如果我们执行IDispose-"能力"在这些对象,其责任是处置的记录象?
你怎么想?我想观点、良好的和坏的。
解决方案
(免责声明:我回答这个基础上java的东西。虽然我的程序C#我有没有代理的任何C#但我知道这是可能的。抱歉java术语)
你可以让国际奥委会框架内进行检查的对象正在建造,看它是否支持 IDisposable.如果不是,你可以使用一个动态代理包裹的实际目的,国际奥委会框架提供给客户的代码。这一动态代理可能实现IDisposable,这样,你总是提供一个IDisposable给客户。只要你使用的接口,这应该是相当简单吗?
然后你就有问题的通信的开发 时 对象是一个IDisposable.我真的不知道这怎么会做一个好的方式。
其他提示
一个选择可能是去工厂案,以便创建的对象直接通过国际奥委会的容器不需要设置自己,例如:
IBinaryDataProviderFactory factory =
ServiceContainer.Global.Resolve<IBinaryDataProviderFactory>();
using(IBinaryDataProvider provider = factory.CreateProvider())
{
...
}
缺点是增加的复杂性,但这并不意味着容器永远不会造成任何开发商是应该处置的-这是总是明确的代码这样做。
如果你真的想让它显而易见,该工厂的方法可以命名为类似CreateDisposableProvider().
你实际上想出了一个非常肮脏的解决方案:你的 IService
合同违反了 SRP, ,这是一个很大的不-没有。
我的建议是以区别所谓的"单独"的服务,从所谓的"原型"服务。寿命的"单独"的管理的容器,这可以查询在运行时是否一个特别实例,实现了 IDisposable
和调用 Dispose()
在关闭如果是这样。
管理原型,另一方面,是完全的责任的呼叫代码。