Fork me on GitHub
Microsoft.Practices.ServiceLocation 之 动态单例模式

Microsoft.Practices.ServiceLocation 之 动态单例模式

背景

 

框架开发中,经常会用到“单例模式”,但是传统的单例模式不支持多态和运行时变化,在关注测试的今天,这种模式是不可行的。为了应对这种情况,微软又提供了另外一种模式,暂且将其称为“动态单例模式”。 我也想统一我的框架对单例的使用模式,因此就写了这篇文章。

 

Microsoft.Practices.ServiceLocation 核心代码

 

看完代码,如何使用这种模式就不用我多介绍了。

 

IServiceLocator

 

View Code
1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace Microsoft.Practices.ServiceLocation
 5 {
 6     /// <summary>
 7     /// The generic Service Locator interface. This interface is used
 8     /// to retrieve services (instances identified by type and optional
 9     /// name) from a container.
10     /// </summary>
11     public interface IServiceLocator : IServiceProvider
12     {
13         /// <summary>
14         /// Get an instance of the given <paramref name="serviceType"/>.
15         /// </summary>
16         /// <param name="serviceType">Type of object requested.</param>
17         /// <exception cref="ActivationException">if there is an error resolving
18         /// the service instance.</exception>
19         /// <returns>The requested service instance.</returns>
20         object GetInstance(Type serviceType);
21 
22         /// <summary>
23         /// Get an instance of the given named <paramref name="serviceType"/>.
24         /// </summary>
25         /// <param name="serviceType">Type of object requested.</param>
26         /// <param name="key">Name the object was registered with.</param>
27         /// <exception cref="ActivationException">if there is an error resolving
28         /// the service instance.</exception>
29         /// <returns>The requested service instance.</returns>
30         object GetInstance(Type serviceType, string key);
31 
32         /// <summary>
33         /// Get all instances of the given <paramref name="serviceType"/> currently
34         /// registered in the container.
35         /// </summary>
36         /// <param name="serviceType">Type of object requested.</param>
37         /// <exception cref="ActivationException">if there is are errors resolving
38         /// the service instance.</exception>
39         /// <returns>A sequence of instances of the requested <paramref name="serviceType"/>.</returns>
40         IEnumerable<object> GetAllInstances(Type serviceType);
41 
42         /// <summary>
43         /// Get an instance of the given <typeparamref name="TService"/>.
44         /// </summary>
45         /// <typeparam name="TService">Type of object requested.</typeparam>
46         /// <exception cref="ActivationException">if there is are errors resolving
47         /// the service instance.</exception>
48         /// <returns>The requested service instance.</returns>
49         TService GetInstance<TService>();
50 
51         /// <summary>
52         /// Get an instance of the given named <typeparamref name="TService"/>.
53         /// </summary>
54         /// <typeparam name="TService">Type of object requested.</typeparam>
55         /// <param name="key">Name the object was registered with.</param>
56         /// <exception cref="ActivationException">if there is are errors resolving
57         /// the service instance.</exception>
58         /// <returns>The requested service instance.</returns>
59         TService GetInstance<TService>(string key);
60 
61         /// <summary>
62         /// Get all instances of the given <typeparamref name="TService"/> currently
63         /// registered in the container.
64         /// </summary>
65         /// <typeparam name="TService">Type of object requested.</typeparam>
66         /// <exception cref="ActivationException">if there is are errors resolving
67         /// the service instance.</exception>
68         /// <returns>A sequence of instances of the requested <typeparamref name="TService"/>.</returns>
69         IEnumerable<TService> GetAllInstances<TService>();
70     }
71 }

 

ServiceLocatorProvider

 

View Code
 1 namespace Microsoft.Practices.ServiceLocation
 2 {
 3     /// <summary>
 4     /// This delegate type is used to provide a method that will
 5     /// return the current container. Used with the <see cref="ServiceLocator"/>
 6     /// static accessor class.
 7     /// </summary>
 8     /// <returns>An <see cref="IServiceLocator"/>.</returns>
 9     public delegate IServiceLocator ServiceLocatorProvider();
10 }

 

ServiceLocator

 

View Code
1 namespace Microsoft.Practices.ServiceLocation
 2 {
 3     /// <summary>
 4     /// This class provides the ambient container for this application. If your
 5     /// framework defines such an ambient container, use ServiceLocator.Current
 6     /// to get it.
 7     /// </summary>
 8     public static class ServiceLocator
 9     {
10         private static ServiceLocatorProvider currentProvider;
11 
12         /// <summary>
13         /// The current ambient container.
14         /// </summary>
15         public static IServiceLocator Current
16         {
17             get { return currentProvider(); }
18         }
19 
20         /// <summary>
21         /// Set the delegate that is used to retrieve the current container.
22         /// </summary>
23         /// <param name="newProvider">Delegate that, when called, will return
24         /// the current ambient container.</param>
25         public static void SetLocatorProvider(ServiceLocatorProvider newProvider)
26         {
27             currentProvider = newProvider;
28         }
29     }
30 }

 

动态单例模式的优点

 

  1. 支持多态。
  2. 运行时可变。
  3. 支持其它级别范围的单例,如:请求级、线程级和会话级等。
  4. 支持对象池。

    纯CSS3实现手风琴风格菜单

    今天分享一个如何使用纯CSS3创建手风琴风格菜单教程,菜单主要通过使用:target伪类来实现。

    css3-accordion-main

    查看演示   下载源码

    :target使用介绍

    CSS3 target伪类是众多实用的CSS3特性中的一个。它用来匹配文档(页面)的URI中某个标志符的目标元素。具体来说,URI中的标志符通常会包含一 个”#”字符,然后后面带有一个标志符名称,比如#respond,target就是用来匹配ID为respond的元素的。
    现在在页面中,点击一个ID链接后,页面只会跳转到相应的位置,但是并不会有比较明显的UI标识,使用:target伪类可以像:hover等伪类一样对目标元素定义样式。

    第一步:HTML标签结构

    一 个简单的无序列表,每个li中包含一个超链接和span,同时为每一个li添加一个不同的id和一个连接到这个id的超链接。为了添加样式和展开菜单项下 面的内容,需要使用:target伪类。

    复制代码
     1 <ul class="accordion">
     2 
     3     <li id="one" class="files"><a href="#one">我的文件<span>495</span></a></li>
     4 
     5     <li id="two" class="mail"><a href="#two">邮件<span>26</span></a></li>
     6 
     7     <li id="three" class="cloud"><a href="#three">网盘<span>58</span></a></li>
     8 
     9     <li id="four" class="sign"><a href="#four">退出登录</a></li>
    10 
    11 </ul>
    复制代码

    第二步:菜单布局基本样式

    首先修改一些浏览器默认 样式,清除margin padding等等。

    复制代码
     1 .accordion,
     2 .accordion ul,
     3 .accordion li,
     4 .accordion a,
     5 .accordion span {
     6     margin: 0;
     7     padding: 0;
     8     border: none;
     9     outline: none;
    10     text-align:left;
    11 }
    12 
    13 .accordion li {
    14     list-style: none;
    15 }
    复制代码

    定义菜单项链接样式,添加渐变,阴影的效果,定义字体等。这里没有指定固定的宽度,菜单的 宽度100%填充它的父元素,如果你想把菜单设置成300px,你可以给它添加一个父div,指定宽度为300px就可以了。虽然没有指定宽度,但是定义 了最小宽度,保证菜单布局能够正确的显示。

    复制代码
     1 .accordion li > a {
     2     display: block;
     3     position: relative;
     4     min-width: 110px;
     5     padding: 0 10px 0 40px;
     6 
     7     color: #fdfdfd;
     8     font: bold 14px/32px 黑体,宋体;
     9     text-decoration: none;
    10     text-shadow: 0px 1px 0px rgba(0,0,0, .35);
    11 
    12     background: #6c6e74;
    13     background: -moz-linear-gradient(top,  #6c6e74 0%, #4b4d51 100%);
    14     background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6c6e74), color-stop(100%,#4b4d51));
    15     background: -webkit-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
    16     background: -o-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
    17     background: -ms-linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
    18     background: linear-gradient(top,  #6c6e74 0%,#4b4d51 100%);
    19 
    20     -webkit-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    21     -moz-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    22     box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    23 }
    复制代码

    定义数字指示器样式,当然如果你的菜单不需要数字指示器,你打可以删掉这个html结构中 span元素。

    复制代码
     1 .accordion li > a span {
     2     display: block;
     3     position: absolute;
     4     top: 7px;
     5     right: 0;
     6     padding: 0 10px;
     7     margin-right: 10px;
     8 
     9     font: normal bold 12px/18px Arial, sans-serif;
    10     background: #404247;
    11 
    12     -webkit-border-radius: 15px;
    13     -moz-border-radius: 15px;
    14     border-radius: 15px;
    15 
    16     -webkit-box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);
    17     -moz-box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);
    18     box-shadow: inset 1px 1px 1px rgba(0,0,0, .2), 1px 1px 1px rgba(255,255,255, .1);
    19 }
    复制代码

    第三步:添加图标样式

    我们使用:before为菜单插入图标,图标的宽 高都是24px,用下面的样式使其正确的显示。我创建了一个sprite,包含了四个图标的正常和hover时候的不同样式。

    复制代码
     1 .accordion > li > a:before {
     2     position: absolute;
     3     top: 0;
     4     left: 0;
     5     content: '';
     6     width: 24px;
     7     height: 24px;
     8     margin: 4px 8px;
     9 
    10     background-repeat: no-repeat;
    11     background-image: url(../images/icons.png);
    12     background-position: 0px 0px;
    13 }
    14 
    15 .accordion li.files > a:before { background-position: 0px 0px; }
    16 .accordion li.files:hover > a:before,
    17 .accordion li.files:target > a:before { background-position: 0px -24px; }
    18 
    19 .accordion li.mail > a:before { background-position: -24px 0px; }
    20 .accordion li.mail:hover > a:before,
    21 .accordion li.mail:target > a:before { background-position: -24px -24px; }
    22 
    23 .accordion li.cloud > a:before { background-position: -48px 0px; }
    24 .accordion li.cloud:hover > a:before,
    25 .accordion li.cloud:target > a:before { background-position: -48px -24px; }
    26 
    27 .accordion li.sign > a:before { background-position: -72px 0px; }
    28 .accordion li.sign:hover > a:before,
    29 .accordion li.sign:target > a:before { background-position: -72px -24px; }
    复制代码

    第四步:子菜单HTML和样式

    HTML:

    同 样也使用ul作为子菜单,放到父菜单的li里面,如下代码:

    复制代码
     1 <li id="one"><a href="#one">我的文件<span>495</span></a>
     2     <ul>
     3 
     4         <li><a href="javascript:void(0);"><em>01</em>音乐<span>42</span></a></li>
     5 
     6         <li><a href="javascript:void(0);"><em>02</em>视频<span>87</span></a></li>
     7 
     8         <li><a href="javascript:void(0);"><em>03</em>图片<span>366</span></a></li>
     9     </ul>
    10 
    11 </li>
    复制代码

    CSS:

    复制代码
     1 .sub-menu li a {
     2     font: bold 12px/32px 黑体,宋体;
     3     color: #797979;
     4     text-shadow: 1px 1px 0px rgba(255,255,255, .2);
     5 
     6     background: #e5e5e5;
     7     border-bottom: 1px solid #c9c9c9;
     8 
     9     -webkit-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    10     -moz-box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    11     box-shadow: inset 0px 1px 0px 0px rgba(255,255,255, .1), 0px 1px 0px 0px rgba(0,0,0, .1);
    12 }
    13 
    14 .sub-menu li:last-child a { border: none; }
    15 
    16 .sub-menu li > a span {
    17     color: #797979;
    18     text-shadow: 1px 1px 0px rgba(255,255,255, .2);
    19     background: transparent;
    20     border: 1px solid #c9c9c9;
    21 
    22     -webkit-box-shadow: none;
    23     -moz-box-shadow: none;
    24     box-shadow: none;
    25 }
    26 
    27 .sub-menu em {
    28     position: absolute;
    29     top: 0;
    30     left: 0;
    31     margin-left: 14px;
    32     color: #a6a6a6;
    33     font: normal 10px/32px Arial, sans-serif;
    34 }
    复制代码

    第五步:定义鼠标悬浮和菜单激活时状态样式

    当鼠标悬浮和菜单激活时改变 背景为绿色。

    复制代码
     1 .accordion > li:hover > a,
     2 .accordion > li:target > a {
     3     color: #3e5706;
     4     text-shadow: 1px 1px 1px rgba(255,255,255, .2);
     5     background: #a5cd4e;
     6     background: -moz-linear-gradient(top,  #a5cd4e 0%, #6b8f1a 100%);
     7     background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a5cd4e), color-stop(100%,#6b8f1a));
     8     background: -webkit-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
     9     background: -o-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
    10     background: -ms-linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
    11     background: linear-gradient(top,  #a5cd4e 0%,#6b8f1a 100%);
    12 }
    13 
    14 .accordion > li:hover > a span,
    15 .accordion > li:target > a span {
    16     color: #fdfdfd;
    17     text-shadow: 0px 1px 0px rgba(0,0,0, .35);
    18     background: #3e5706;
    19 }
    20 
    21 .sub-menu li:hover a { background: #efefef; }
    复制代码

    第六步:控制子菜单的显示与隐藏

    为 了隐藏子菜单,我们需要定义子菜单的高度为0px。当点击父菜单时,为子菜单添加下滑显示的动态效果。为了实现下滑的效果,需要指定子菜单固定的高度。因 为这个教程中子菜单有三个link,所以这里指定了98px。如果你想加更多的子菜单就需要修改height为所有子菜单的高度和,当然如果你想要让它自 动变化,可以给高度赋值100%,但是这样下滑的动画效果就没有了。

    复制代码
     1 .accordion li > .sub-menu {
     2     height: 0;
     3     overflow: hidden;
     4 
     5     -webkit-transition: all .2s ease-in-out;
     6     -moz-transition: all .2s ease-in-out;
     7     -o-transition: all .2s ease-in-out;
     8     -ms-transition: all .2s ease-in-out;
     9     transition: all .2s ease-in-out;
    10 }
    11 
    12 .accordion li:target > .sub-menu {
    13     height: 98px;
    14 }
    复制代码

    总结:

    到此纯CSS3实现的手风琴风格菜单就全部结束了。教程中我们主要通过使用伪类:before和:target来定义样式,使用:target来实现菜单点击展开子菜单事件。希望你能够喜欢这个教程。

     
     
    分类: CSS3

posted on 2013-05-06 13:30  HackerVirus  阅读(1332)  评论(0编辑  收藏  举报