首页 > 代码库 > My.Ioc 代码示例——使用 Observer 机制捕获注册项 (Registration) 状态的变化

My.Ioc 代码示例——使用 Observer 机制捕获注册项 (Registration) 状态的变化

在 My.Ioc 中,要想在服务注销/注册时获得通知,可以通过订阅 ObjectBuilderRegistered 和 ObjectBuilderUnregistering 这两个事件来实现。但是,使用这两个事件也有一些不足。首先,它们只能针对当前注册/注销的服务发出通知,而对于依赖当前服务的上层服务的激活/停用事件(由于当前服务的注册/注销而引起的),它们则无能为力;其次,这两者都是针对所有注册项的广播事件。也就是说,只要发生注册/注销,无论注册/注销的是什么服务,容器都会向所有订阅了这两个事件的处理程序 (Event Handler) 发出通知。

由于上面这些限制因素,我们在 My.Ioc 中提供了 IObjectObserver/IObjectCollectionObserver 的机制。使用 IObjectObserver/IObjectCollectionObserver,用户可以实现针对特定契约类型 (Contract Type) 的更加高效和实时的侦听。

在这两者中,IObjectObserver 侦听的是一个实现了某个契约的服务,而 IObjectCollectionObserver 侦听的则是一组实现了相同契约的服务。下面我们通过代码示例来了解它们的用法:

using System;using System.Collections.Generic;using My.Ioc;namespace ObserverUsage{    #region ObjectObserver Types    public class ServiceConsumer    {        Service _service;        public ServiceConsumer(Service service)        {            _service = service;        }    }    public class Service    {    }    #endregion    #region ObjectCollectionObserver Types    public class Tree    {        readonly IList<Node> _childNodes;        public Tree(IList<Node> childNodes)        {            _childNodes = new List<Node>(childNodes);        }        public IList<Node> ChildNodes        {            get { return _childNodes; }        }    }    public abstract class Node    {        string _name;        public string Name        {            get            {                _name = _name ?? GetType().Name;                return _name;            }        }    }    public class Node1 : Node    {    }    public class Node2 : Node    {    }    public class Node3 : Node    {    }    public class Node4 : Node    {    }    #endregion    class Program    {        private static IObjectContainer _container;        static void Main(string[] args)        {            _container = new ObjectContainer(false);            RunObjectObserverTest();            RunObjectCollectionObserverTest();            Console.ReadLine();        }        #region ObjectObserver        static void RunObjectObserverTest()        {            IObjectRegistration<Service> serviceRegistration;            IObjectObserver<ServiceConsumer> consumerObserver;            IObjectObserver<Service> serviceObserver;            // Register and commit            _container.Register<Service>().Return(out serviceRegistration);            _container.Register<ServiceConsumer>();            _container.CommitRegistrations();            // Try to get the ObjectObserver and hook events            if (_container.TryGetObserver(out serviceObserver))                serviceObserver.Changed += OnObjectBuilderChangedForService;            if (_container.TryGetObserver(out consumerObserver))                consumerObserver.Changed += OnObjectBuilderChangedForConsumer;            // Try to resolve an instance of ServiceConsumer to build the relationship between the             // ServiceConsumer and Service, so that if we unregistered the Service, not only the             // service observer, but also the consumer observer, will receive the notification.            var consumer = _container.Resolve<ServiceConsumer>();            // Unregister the Service. The observers should receive the notification later.            _container.Unregister(serviceRegistration);            // Dispose the observers            consumerObserver.Dispose();            serviceObserver.Dispose();        }        static void OnObjectBuilderChangedForService(ObjectBuilderChangedEventArgs args)        {            if (args.ChangeMode == ObjectBuilderChangeMode.Activate)                Console.WriteLine("The Service is activated...");            else if (args.ChangeMode == ObjectBuilderChangeMode.Deactivate)                Console.WriteLine("The Service is deactivated...");        }        static void OnObjectBuilderChangedForConsumer(ObjectBuilderChangedEventArgs args)        {            if (args.ChangeMode == ObjectBuilderChangeMode.Activate)                Console.WriteLine("The ServiceConsumer is activated...");            else if (args.ChangeMode == ObjectBuilderChangeMode.Deactivate)                Console.WriteLine("The ServiceConsumer is deactivated...");        }        #endregion        #region ObjectCollectionObserver                private static Tree _tree;        static void RunObjectCollectionObserverTest()        {            IObjectRegistration<Node> nodeRegistration;            IObjectCollectionObserver<Node> nodesObserver;            // Register and commit            _container.Register<Node, Node1>().Return(out nodeRegistration);            _container.Register<Node, Node2>();            _container.Register<Node, Node3>();            _container.Register<Node, Node4>();            _container.CommitRegistrations();            // Try to get the ObjectObserver and hook events            if (_container.TryGetObserver(out nodesObserver))                nodesObserver.Changed += OnObjectBuilderChangedForNodeCollection;            var nodes = _container.ResolveAll(nodesObserver);            _tree = new Tree(nodes);            PrintTree();            // Unregister the Service. The observers should receive the notification later.            _container.Unregister(nodeRegistration);            PrintTree();            _container.Register<Node, Node1>();            _container.CommitRegistrations();            PrintTree();            // Dispose the observer            nodesObserver.Dispose();        }        static void PrintTree()        {            Console.WriteLine();            foreach (var node in _tree.ChildNodes)                Console.WriteLine(node.Name);        }        static void OnObjectBuilderChangedForNodeCollection(ObjectBuilderCollectionChangedEventArgs args)        {            if (args.ChangeMode == ObjectBuilderCollectionChangeMode.Add)            {                var node = (Node)_container.Resolve(args.ObjectBuilder, null);                _tree.ChildNodes.Add(node);            }            else if (args.ChangeMode == ObjectBuilderCollectionChangeMode.Remove)            {                _tree.ChildNodes.RemoveAt(args.Position);            }        }                #endregion    }}
View Code

在上述示例中,我们简单演示了 IObjectObserver/IObjectCollectionObserver 的使用方法。

恰如您在示例中看到的,使用 IObjectObserver,当服务停用(注销)/激活(注册)时,该服务的观察者 (Observer) 以及任何依赖于该服务的上层服务的观察者都会收到通知,而用户可以于此时在处理程序中执行一些操作,从而更好地响应服务变化。

与 IObjectObserver 相比,IObjectCollectionObserver 的用法略有一点不同,因为它侦听的是一组而不是一个服务。使用 IObjectCollectionObserver 时,当某个服务注册/注销时,如果该服务或者它的任何上层服务处于 IObjectCollectionObserver 的侦听之中,IObjectCollectionObserver 便会发出通知,这样我们就会获知位于集合中哪个位置 (Position) 的服务被停用(注销)/激活(注册)的信息,从而可以根据此通知信息在处理程序中执行相应的操作,以更新(删除/添加)服务集合(示例中的节点树)

 

本文源码可从此处下载。

My.Ioc 代码示例——使用 Observer 机制捕获注册项 (Registration) 状态的变化