DryIOC支持多种状态的Service,瞬态服务(Reuse.Transient Service)仅是其中一种。意味着该服务不会被重用。调用Resove方法或者注入时,都会重新创建一个服务实例。当你在注册服务时省略reuse参数或者没有改变容器的 Container.Rules.DefaultReuse属性,瞬态服务是容器的默认状态。
container.Register1. 实现IDisposable接口的瞬态服务(Reuse.Transient); container.Register ();
当您注册的服务实现了IDispoable接口,该瞬态服务的释放职责将编程一个问题。这需要分成两种情况进行讨论。
1.1 通过Resolve方法获取瞬态服务实例注意
DryIOC默认情况下不支持实现IDispoable接口的瞬态服务的注册。可通过以下两种方式就行配置以实现支持:
- 在调用注册函数时,设置allowDisposableTransient: true。这种方式仅影响当前注册的服务
- 在创建容器时使用Rules.WithoutThrowonRegisteringDisposableTransient() 修改容器规则。这种方式是全局的
产生问题的原因
如果允许注册实现了IDisposable接口的服务,那么需要开发者自行管理创建的瞬态服务实例的释放工作。
// 定义容器变量
Container container;
// 指示是否通过全局方式允许容器支持实现`IDisposable`接口的瞬态服务
bool isUseGlobelFlag = false;
void Main()
{
System.Console.WriteLine("容器创建");
if (isUseGlobelFlag)
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient());
else
container = new Container();
// 执行方法
DisposableTransientService();
System.Console.WriteLine("容器释放");
container.Dispose();
System.Console.WriteLine("程序结束");
}
void DisposableTransientService()
{
System.Console.WriteLine("服务注册");
if (isUseGlobelFlag)
container.Register();
else
container.Register(setup:Setup.With(allowDisposableTransient:true));
System.Console.WriteLine("服务解析");
var x = container.Resolve();
x.Dispose();
}
class X : System.IDisposable
{
public X()
{
System.Console.WriteLine(nameof(X) + " is created.");
}
public void Dispose()
{
System.Console.WriteLine(nameof(X) + " is disposed.");
}
}
容器创建
服务注册
服务解析
X is created.
X is disposed.
容器释放
程序结束
上述程序的运行结果不会出现任何问题,因为我们可以手动的对瞬态服务的实例进行释放。如果注释掉DisposableTransientService方法种的x.Dispose();语句,运行后可以发现,x的释放工作将不被执行。这也从侧面验证了当允许容器注册实现了IDispoable接口的瞬态服务,瞬态服务实例的释放将不被执行。
1.2 通过注入的方式获取瞬态服务实例容器创建
服务注册
服务解析
X is created.
容器释放
程序结束
// 定义容器变量
Container container;
// 指示是否通过全局方式允许容器支持实现`IDisposable`接口的瞬态服务
bool isUseGlobelFlag = false;
void Main()
{
System.Console.WriteLine("容器创建");
if (isUseGlobelFlag)
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient());
else
container = new Container();
// 执行方法
DisposableTransientService();
System.Console.WriteLine("容器释放");
container.Dispose();
System.Console.WriteLine("程序结束");
}
void DisposableTransientService()
{
System.Console.WriteLine("服务注册");
if (isUseGlobelFlag)
container.Register();
else
container.Register(setup:Setup.With(allowDisposableTransient:true));
container.Register();
System.Console.WriteLine("服务解析");
var user = container.Resolve();
}
class X : System.IDisposable
{
public X()
{
System.Console.WriteLine(nameof(X) + " is created.");
}
public void Dispose()
{
System.Console.WriteLine(nameof(X) + " is disposed.");
}
}
class XUser
{
public XUser(X x)
{
System.Console.WriteLine(nameof(XUser) + " is created.");
}
}
容器创建
服务注册
服务解析
X is created.
XUser is created.
容器释放
程序结束
这里实现IDisposable接口的瞬态服务被作为XUser类构造函数的一个依赖。这种情况下,我们无法获得X类型的注入实例,也就无法手动进行释放。从而导致释放的问题。
2. 实现IDisposable接口的瞬态服务的跟踪为了解决上述问题,DryIOC提供了一种机制对注入的瞬态服务进行跟踪,以便在适当的时候进行释放。
// 定义容器变量
Container container;
// 指示是否通过全局方式跟踪实现`IDisposable`接口的瞬态服务
bool isUseGlobelTrack = false;
void Main()
{
System.Console.WriteLine("容器创建");
if (isUseGlobelTrack)
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient().WithTrackingDisposableTransients());
else
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient());
// 执行方法
DisposableTransientService();
System.Console.WriteLine("容器释放");
container.Dispose();
System.Console.WriteLine("程序结束");
}
void DisposableTransientService()
{
System.Console.WriteLine("服务注册");
if (isUseGlobelTrack)
container.Register();
else
container.Register(setup:Setup.With(trackDisposableTransient:true));
container.Register();
System.Console.WriteLine("服务解析");
var user = container.Resolve();
}
class X : System.IDisposable
{
public X()
{
System.Console.WriteLine(nameof(X) + " is created.");
}
public void Dispose()
{
System.Console.WriteLine(nameof(X) + " is disposed.");
}
}
class XUser
{
public XUser(X x)
{
System.Console.WriteLine(nameof(XUser) + " is created.");
}
}
容器创建
服务注册
服务解析
X is created.
XUser is created.
容器释放
X is disposed.
程序结束
由结果可以看出,瞬态服务释放的问题得到解决。
3. 阻止瞬态服务的跟踪 3.1 方式一:指定preventDisposal=true// 定义容器变量
Container container;
void Main()
{
System.Console.WriteLine("容器创建");
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient().WithTrackingDisposableTransients());
// 执行方法
DisposableTransientService();
System.Console.WriteLine("容器释放");
container.Dispose();
System.Console.WriteLine("程序结束");
}
void DisposableTransientService()
{
System.Console.WriteLine("服务注册");
container.Register(setup:Setup.With(preventDisposal:true));
container.Register();
System.Console.WriteLine("服务解析");
var user = container.Resolve();
}
class X : System.IDisposable
{
public X()
{
System.Console.WriteLine(nameof(X) + " is created.");
}
public void Dispose()
{
System.Console.WriteLine(nameof(X) + " is disposed.");
}
}
class XUser
{
public XUser(X x)
{
System.Console.WriteLine(nameof(XUser) + " is created.");
}
}
3.2 方式二:使用Func容器创建
服务注册
服务解析
X is created.
XUser is created.
容器释放
程序结束
// 定义容器变量
Container container;
XFactory xf;
static X xGlobal;
void Main()
{
System.Console.WriteLine("容器创建");
container = new Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient().WithTrackingDisposableTransients());
// 执行方法
DisposableTransientService();
System.Console.WriteLine("容器释放");
container.Dispose();
// 获取时创建一个心的X
var xx = xf.GetX();
Console.WriteLine(xx == xf.X);
System.Console.WriteLine("程序结束");
}
void DisposableTransientService()
{
System.Console.WriteLine("服务注册");
container.Register();
container.Register();
System.Console.WriteLine("服务解析");
Console.WriteLine("=========================");
xf = container.Resolve();
}
class X : System.IDisposable
{
public X()
{
System.Console.WriteLine(nameof(X) + " is created.");
}
public void Dispose()
{
System.Console.WriteLine(nameof(X) + " is disposed.");
}
}
class XFactory
{
public readonly Func GetX;
public readonly X X;
// 注入x时创建一个X
public XFactory(Func getX, X x)
{
Console.WriteLine("=========================");
xGlobal = x;
this.X = x;
this.GetX = getX;
System.Console.WriteLine(nameof(XFactory) + " is created.");
}
}
容器创建
服务注册
服务解析
=========================
X is created.
=========================
XFactory is created.
容器释放
X is disposed.
X is created.
False
程序结束
在构造XFactory时通过构造函数的参数x完成了一次注入,此时创建了一个X的实例。该实例在容器给释放时被释放。指定var xx = xf.GetX();语句时重新创建了一个X的实例。两次创建的实例不相同。
4. 使用其他默认reuse代替瞬态服务void Main()
{
var container = new Container(rules => rules.WithDefaultReuse(Reuse.Scoped));
container.Register();
using (var scope = container.OpenScope())
{
var abc = scope.Resolve();
Console.WriteLine(abc == scope.Resolve());
}
}
class Abc { }
True
在同一个Scope中创建的实例是相同的.



