关于Autofac的使用陷阱
说明:本文是对参考文章的一个整理,做一个记录,基本没有翻译,详情请参看原文.
使用注意要点:
Autofac will track every disposable component instance that it creates, no matter how that instance is requested.
Don’t resolve from the root container. Always resolve from and then release a lifetime scope.
不推荐、不宜的用法:
一、
interface IMyResource { … }
class MyResource : IMyResource, IDisposable { … }
When an instance of MyResource is created in an Autofac container, the container will hold a reference to it even when it is no longer being used by the rest of the program. This means that the garbage collector will be unable to reclaim the memory held by that component, so the following program will eventually exhaust all available memory and crash
var builder = new ContainerBuilder();
builder.RegisterType<MyResource>().As<IMyResource>();
using (var container = builder.Build())
{
while (true)
var r = container.Resolve<IMyResource>(); // Out of memory!
}
his is a far cry from typical CLR behaviour, which is one more reason why it is good to get away from thinking about an IoC container as a replacement fornew. If we’d just createdMyResourcedirectly in the loop, there wouldn’t be any problem at all
while (true)
var r = new MyResource(); // Fine, feed the GC
二、
interface IMyService { }
class MyComponent : IMyService
{
// Dependency on a service provided by a disposable component
public MyComponent(IMyResource resource) { … }
}
If a second component is resolved that depends on a service provided by a disposable component, the memory leak still occurs
while (true)
// Still holds instances of MyResource
var s = container.Resolve<IMyService>();
三、
interface IMyService2
{
void Go();
} class MyComponent2 : IMyService2
{
Func<IMyResource> _resourceFactory; public MyComponent(Func<IMyResource> resourceFactory)
{
_resourceFactory = resourceFactory;
} public void Go()
{
while (true)
var r = _resourceFactory(); // Still out of memory.
}
}
有什么方式可以改善上面的情况呢?
答:lifetime Scopes
// var container = …
while (true)
{
using (var lifetimeScope = container.BeginLifetimeScope())
{
var r = lifetimeScope.Resolve<IMyResource>();
// r, all of its dependencies and any other components
// created indirectly will be released here
}
}
Lifetime Scopes 可以被嵌套使用:
var ls1 = container.BeginLifetimeScope();
var ls2 = ls1.BeginLifetimeScope();
// ls1 is a child of the container, ls2 is a child of ls1
Lifetime Scopes 不会产生上下文依赖:
var ls1 = container.BeginLifetimeScope();
var ls2 = container.BeginLifetimeScope();
// ls1 and ls2 are completely independent of each other
Owned Instance:
Owned instances (Owned<T>) are the last tale in Autofac’s lifetime story.
An owned instance is a component that comes wrapped in its own lifetime scope. This makes it easier to keep track of how a component should be released, especially if it is used outside of a using statement.
To get an owned instance providing service T, you can resolve one directly from the container
var ownedService = container.Resolve<Owned<IMyService>>();
In lifetime terms, this is equivalent to creating a new lifetime scope from the container, and resolving IMyService from that. The only difference is that the IMyService and the lifetime scope that holds it come wrapped up together in a single object.
The service implementation is available through the Value property:
// Value is IMyService
ownedService.Value.DoSomething();
When the owned instance is no longer needed, it and all of its disposable dependencies can be released by disposing the Owned<T> object:
ownedService.Dispose();
Owner Instance 与 Fun 结合使用:
Components that are returned from Func<T> delegates are associated with the same lifetime scope as the delegate itself. If that component is itself contained in a lifetime scope, and it creates a finite number of instances through the delegate, then there’s no problem – everything will be cleaned up when the scope completes.
If the component calling the delegate is a long-lived one, then the instances returned from the delegate will need to be cleaned up eagerly. To do this, Owned<T> can be used as the return value of a factory delegate
class MyComponent2 : IMyService2
{
Func<Owned<IMyResource>> _resourceFactory; public MyComponent(Func<Owned<IMyResource>> resourceFactory)
{
_resourceFactory = resourceFactory;
} public void Go()
{
while (true)
using (var r = _resourceFactory())
// Use r.Value before disposing it
}
}Func<T>andOwned<T>can be combined with other relationship types to define relationships with a clearer intent than just taking a dependency onILifetimeScope
参考文章:
http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/
http://nblumhardt.com/2010/01/the-relationship-zoo/
关于Autofac的使用陷阱的更多相关文章
- 深入理解Autofac生命周期
为什么Autofac表现的这样? 这里似乎有几个陷阱,虽然这里只有一个------并且这个值得重申: Autofac将会跟踪每一个他所创建的可销毁的组件实例,无论这个实例是怎样被获取的. 当然,最终. ...
- Autofac容器对象实例的几种生命周期类型
实例范围决定了如何在同一服务的请求之间共享实例. 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况. 当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作 ...
- .NET手记-为ASP.NET MVC程序集成Autofac
MVC Autofac总是会紧跟最新版本的ASP.NET MVC框架,所以文档也会一直保持更新.一般来讲,不同版本的框架集成Autofac的方法一般不变. MVC集成需要引用 Autofac.Mvc5 ...
- autofac生命周期入门(如何避免内存泄漏)
如果你是一个IOC新手,那么生命周期可能会比较难以理解.以至于谈到这个问题时,一些老手也时常表示疑虑和害怕.一个令人不安的问题就是-对象没有在合适的时机被销毁.这样一来内存的使用率就会一直攀升,直到程 ...
- AutoFac在项目中的应用
技能大全:http://www.cnblogs.com/dunitian/p/4822808.html#skill 完整Demo:https://github.com/dunitian/LoTCode ...
- Autofac - MVC/WebApi中的应用
Autofac前面写了那么多篇, 其实就是为了今天这一篇, Autofac在MVC和WebApi中的应用. 一.目录结构 先看一下我的目录结构吧, 搭了个非常简单的架构, IOC(web), IBLL ...
- Autofac - 生命周期
实例生命周期决定在同一个服务的每个请求的实例是如何共享的. 当请求一个服务的时候,Autofac会返回一个单例 (single instance作用域), 一个新的对象 (per lifetime作用 ...
- Autofac - 属性注入
属性注入不同于通过构造函数方式传入参数. 这里是通过注入的方式, 在类创建完毕之后, 资源释放之前, 给属性赋值. 这里, 我重新弄一些类来演示这一篇吧. public class ClassA { ...
- Autofac 的点滴
泛型类型的注册和使用 public interface IRepository<T> where T:class { } public interface ISchoolDetailRep ...
随机推荐
- GridView導出Excel
1.aspx頁面需要添加:EnableEventValidation="false" 實例:<%@ Page Language="C#" AutoEven ...
- IE6 IE7 IE8 的函数声明和函数表达式的实现与其他浏览器有差异
标准参考 函数声明和函数表达式 定义一个函数有两种途径:函数声明和函数表达式. 函数声明: function Identifier ( FormalParameterList opt ) { Func ...
- 新手须知设计的法则 Mark
经常看到一些讲如何学习设计的文章,坦白讲感觉有些千篇一律.且不痛不痒,都说要看点书.学点画.练软件.多观察……唉,练软件这事还要说么,难道你还需要告诉一个人学开发是需要学习编程语言的? 学习是基于过往 ...
- url(data:image/png;base64,R0**)(转)
url(data:image/png;base64,R0**) 所谓"data"类型的Url格式,是在RFC2397中 提出的,目的对于一些"小"的数据,可以在 ...
- 《学习OpenCV》练习题第四章第一题a
#include <highgui.h> #include <cv.h> #pragma comment (lib,"opencv_calib3d231d.lib&q ...
- 通过Microsoft Azure服务设计网络架构的经验分享(转)
原文:http://www.infoq.com/cn/articles/azure-networking-tips 本文从产品设计和架构角度分享了 Microsoft Azure 网络服务方面的使用经 ...
- cocos2d-x 2.2.5 安卓工程编译的问题
原址:http://www.cocoachina.com/bbs/read.php?tid=217124 新的cocos2d-x 2.2.5 在使用Eclipse的安卓NDK 9 的编译器进行编译的时 ...
- Codeforces Round #368 (Div. 2) C. Pythagorean Triples(数学)
Pythagorean Triples 题目链接: http://codeforces.com/contest/707/problem/C Description Katya studies in a ...
- MetaQ安装部署文档
一.MetaQ安装部署情况: 地点 IP Broker ID Master/Slave Slave ID:Group 合肥 192.168.52.23 Slave 1:meta-slave-group ...
- POJ 2342 Anniversary party (树dp)
题目链接:http://poj.org/problem?id=2342 有n个人,每个人有活跃值.下面n-1行u和v表示u的上司是v,有直接上司和下属的关系不能同时参加party,问你party最大的 ...