DryIOC
支持多种状态的Service
,瞬态服务(Reuse.Transient Service)仅是其中一种。意味着该服务不会被重用。调用Resove方法或者注入时,都会重新创建一个服务实例。当你在注册服务时省略reuse
参数或者没有改变容器的 Container.Rules.DefaultReuse
属性,瞬态服务是容器的默认状态。
container.Register<IFoo, Foo>(Reuse.Transient);
container.Register<IFoo, Foo>();
1. 实现IDisposable接口的瞬态服务
当您注册的服务实现了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<X>();
else
container.Register<X>(setup:Setup.With(allowDisposableTransient:true));
System.Console.WriteLine("服务解析");
var x = container.Resolve<X>();
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接口的瞬态服务,瞬态服务实例的释放将不被执行
。
容器创建
服务注册
服务解析
X is created.
容器释放
程序结束
1.2 通过注入的方式获取瞬态服务实例
// 定义容器变量
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<X>();
else
container.Register<X>(setup:Setup.With(allowDisposableTransient:true));
container.Register<XUser>();
System.Console.WriteLine("服务解析");
var user = container.Resolve<XUser>();
}
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<X>();
else
container.Register<X>(setup:Setup.With(trackDisposableTransient:true));
container.Register<XUser>();
System.Console.WriteLine("服务解析");
var user = container.Resolve<XUser>();
}
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<X>(setup:Setup.With(preventDisposal:true));
container.Register<XUser>();
System.Console.WriteLine("服务解析");
var user = container.Resolve<XUser>();
}
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.
容器释放
程序结束
3.2 方式二:使用Func
// 定义容器变量
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<X>();
container.Register<XFactory>();
System.Console.WriteLine("服务解析");
Console.WriteLine("=========================");
xf = container.Resolve<XFactory>();
}
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<X> GetX;
public readonly X X;
// 注入x时创建一个X
public XFactory(Func<X> 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<Abc>();
using (var scope = container.OpenScope())
{
var abc = scope.Resolve<Abc>();
Console.WriteLine(abc == scope.Resolve<Abc>());
}
}
class Abc { }
True
在同一个Scope
中创建的实例是相同
的.