zoukankan      html  css  js  c++  java
  • My.Ioc 代码示例——使用观察者机制捕获注册项状态的变化

    在 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) 的服务被停用(注销)/激活(注册)的信息,从而可以根据此通知信息在处理程序中执行相应的操作,以更新(删除/添加)服务集合(示例中的节点树)

    本文源码可从此处下载。

  • 相关阅读:
    开博客啦
    C语言 变长参数表的使用方法
    禅道程序员
    【转】函数式编程另类指南
    Servlet中JSP页面跳转的两种方法以及其区别
    《C程序设计语言》(学习笔记)——结构体
    C#保存wps和office表格.数据源为list<T>类型
    中国网建的短信接口实现
    C#保存wps和office表格.数据源为list<T>类型,
    MD5加密
  • 原文地址:https://www.cnblogs.com/johnny-liu/p/3962510.html
Copyright © 2011-2022 走看看