My.Ioc 代码示例——注册项的注销和更新
当您需要从 Ioc 容器中注销/删除一个注册项的时候,您会怎么做呢?
有人曾经在 stackoverflow 上提问“如何从 Unity 中注销一个注册项”。对于这个问题,有人的回答是“有趣。你为什么要这样做?”,也有人试图提出一些变通的解决办法,例如通过自定义 LifetimeManager 来实现注销等等。在作者看来,这些其实都不是根本的解决办法。因为服务的注册/注销本身是一个容器级过程,当中会涉及到一些中间对象的创建/清理 (Dispose) 以及不同对象之间的协调,本应由容器来提供支持才对。
遗憾的是,在目前常见的大多数 Ioc 容器中,几乎都不提供此项功能。就作者目前所知,只有一个 Castle Windsor 曾经提供过 Unregister 功能,后来还在 3.0 版本中给去掉了,原因是这些方法 (Unregister) 有问题和瑕疵 (The methods were implementation of "remove component from the container" feature which was flawed and problematic, hecen was scraped)。
服务注销/删除的情况是如此,至于服务更新(在服务注销之后再注册新的服务以替换和更新原有服务)的功能,那更不用说了。
这种情况让作者感到很困惑。难道服务不会过期作废 (Obsolete) 吗?难道服务一旦注册之后,真的不需要注销/更新吗?作者觉得不是这样的。以作者微薄的认知,也可以举出至少两个场景是需要上述功能的:插件环境(在插件环境中,随着插件的更新,有可能需要更新服务)和面向服务环境(在面向服务环境中,服务随时可能会启用/停用/更新)。
因此,作者决定在自己的 My.Ioc 框架中提供注册项的注销/更新功能以试图解决上述问题。用法很简单,可参见下面示例代码:
using System;
using System.Diagnostics;
using My.Ioc; namespace ServiceUpdate
{
#region Test Types public interface IService
{
string Name { get; }
} public abstract class Service : IService
{
public string Name
{
get { return GetType().Name; }
}
} public class Service1 : Service
{
} public class Service2 : Service
{
} public interface IServiceConsumer
{
IService Service { get; }
} public class ServiceConsumer : IServiceConsumer
{
readonly IService _service; public ServiceConsumer(IService service)
{
_service = service;
} public IService Service
{
get { return _service; }
}
} #endregion class Program
{
static void Main(string[] args)
{
IObjectRegistration serviceRegistration;
IObjectContainer container = new ObjectContainer(false);
container.Register<IService, Service1>().Return(out serviceRegistration);
container.Register<IServiceConsumer, ServiceConsumer>();
container.CommitRegistrations(); var consumer = container.Resolve<IServiceConsumer>();
Debug.Assert(consumer != null);
Debug.Assert(consumer.Service != null);
Debug.Assert(consumer.Service.Name == "Service1"); container.Unregister(serviceRegistration);
container.Register<IService, Service2>().Return(out serviceRegistration);
container.CommitRegistrations(); consumer = container.Resolve<IServiceConsumer>();
Debug.Assert(consumer != null);
Debug.Assert(consumer.Service != null);
Debug.Assert(consumer.Service.Name == "Service2"); Console.ReadLine();
}
}
}
源码可在此处下载,压缩包中包含了 My.Ioc 框架的源码和本示例以及其他一些示例的源码。
My.Ioc 代码示例——注册项的注销和更新的更多相关文章
- My.Ioc 代码示例——如何使用默认构造参数,以及如何覆盖默认构造参数
在 Ioc 世界中,有些框架(例如 Autofac/NInject/Unity)支持传递默认参数,有些框架(例如 SimpleInjector/LightInjector 等)则不支持.作为 My.I ...
- My.Ioc 代码示例——使用观察者机制捕获注册项状态的变化
在 My.Ioc 中,要想在服务注销/注册时获得通知,可以通过订阅 ObjectBuilderRegistered 和 ObjectBuilderUnregistering 这两个事件来实现.但是,使 ...
- My.Ioc 代码示例——实现自动注册/解析
在很多 Ioc 容器中,当使用者向容器请求实现了某个契约类型 (Contract Type) 的服务时 (调用类似如下方法 container.Resolve(Type contractType)), ...
- My.Ioc 代码示例——使用条件绑定和元数据(可选)构建插件树
本文旨在通过创建一棵插件树来演示条件绑定和元数据的用法. 说“插件树”也许不大妥当,因为在一般观念中,谈到插件树,我们很容易会想到 Winform/Wpf 中的菜单.举例来说,如果要在 Winform ...
- My.Ioc 代码示例——避免循环依赖
本文的目的在于通过一些示例,向大家说明 My.Ioc 支持哪些类型的依赖关系.也就是说,如何设计对象不会导致循环依赖. 在 Ioc 世界中,循环依赖是一个顽敌.这不仅因为它会导致 Ioc 容器抛出异常 ...
- My.Ioc 代码示例——属性和方法注入
在 My.Ioc 中,我们可以指定让容器在构建好对象实例之后,自动为我们调用对象的公共方法或是为对象的公共属性赋值.在解析对象实例时,容器将根据我们在注册对象时指定的方法调用或属性赋值的先后顺序,调用 ...
- My.Ioc 代码示例——利用 ObjectBuilderRequested 事件实现延迟注册
在使用 Ioc 框架时,一般我们建议集中在一个称为 Composition Root(其含义请参见下面的小注)的位置来注册 (Register) 和解析 (Resolve) 服务.这种做法的目的在于限 ...
- My.Ioc 代码示例——谈一谈如何实现装饰器模式,兼谈如何扩展 My.Ioc
装饰器模式体现了一种“组合优于继承”的思想.当我们要动态为对象增加新功能时,装饰器模式往往是我们的好帮手. 很多后期出现的 Ioc 容器都为装饰器模式提供了支持,比如说 Autofac.在 My.Io ...
- My.Ioc 代码示例——Lifetime 和 ILifetimeScope
很多 Ioc 框架在创建对象的过程中,都会采取某种方式来缓存/复用/释放已构建的对象.在 My.Ioc 中,这个目的是通过 Lifetime/ILifetimeScope 来实现的.其中,Lifeti ...
随机推荐
- [待续]Async in C# 1
异步.异步是在.net .45里面提供的一个新的方法 它主要用在.三个方面 1.网络访问 2.磁盘访问 3.延迟很长时间的步骤 它主要有2个关键字 Async Await Async 怎么工作 d ...
- IBM Websphere 说明文档
http://pic.dhe.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.nd.doc%2Finfo%2F ...
- 日志式文件系统:SGI的xfs, Reiserfs, IBM的jfs, ext3fs
日志文件(Log files)是包含系统消息的文件,包括内核.服务.在系统上运行的应用程序等.不同的日志文件记载不同的信息.日志文件系统比传统的文件系统安全,因为它用独立的日志文件跟踪磁盘内容的变化. ...
- bzoj2730
首先不难想到要先求割顶,求割顶的方法白书上有讲解由于是一个矿崩塌,所以假如一个连通块连接了两个以上割顶,那么这个连通块内显然是不用设出口的连接块只连接了一个割顶,那么出口可以设在这个连通块内任意位置由 ...
- 【转】Android自定义Adapter的ListView的思路及代码
原文网址:http://www.jb51.net/article/37236.htm Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下 在开发中,我们经常使 ...
- 【高精度】NCPC 2014 C catalansqure
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1789 题目大意: 求大卡特兰数..公式如下.输入n求Sn(n<=5000) 题目 ...
- RAII(Resource Acquisition Is Initialization)资源获得式初始化
当在编写代码中用到异常,非常重要的一点是:“如果异常发生,程序占用的资源都被正确地清理了吗?” 大多数情况下不用担心,但是在构造函数里有一个特殊的问题:如果一个对象的构造函数在执行过程中抛出异常,那么 ...
- Java多线程Thread.yield(),thread.join(), Thread.sleep(200),Object.wait(),Object.notify(),Object.notifyAll()的区别
Thread.yield(),在某个线程里调用Thread.yield(),会使这个线程由正在运行的running状态转变为等待cpu时间片的runable状态.join()是Thread类的一个非s ...
- UVALive 5990 Array Diversit
题意:对于一个数列A,substring是一个连续子串,subsequence是其非连续子序列.对于一个数字序列,记它的diversity是它的最大元素减去最小元素的差.给出一个数字序列,求与它div ...
- SVN 基本操作
SVN基础 一 简介 tortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理 ...