【NopCommerce源码架构学习-二】单例模式实现代码分析

单例模式是是常用经典十几种设计模式中最简单的。.NET中单例模式的实现也有很多种方式。下面我来介绍一下NopCommerce中单例模式实现。

我之前的文章就分析了一下nop中EngineContext的实现。EngineContext是把一个Web请求用Nop的EngineContext引擎上下文封装。里面提供了一个IEngine的单例对象的访问方式。

下面就是EngineContext的源码:

一、EngineContext

  1 using System.Configuration;
  2
  3 using System.Runtime.CompilerServices;
  4
  5 using Nop.Core.Configuration;
  6
  7
  8
  9 namespace Nop.Core.Infrastructure
 10
 11 {
 12
 13     /// <summary>
 14
 15     ///Provides access to the singleton instance of the Nop engine.
 16
 17     ///提供了访问单例实例Nop引擎
 18
 19     /// </summary>
 20
 21     public class EngineContext
 22
 23     {
 24
 25         #region Methods
 26
 27
 28
 29         /// <summary>
 30
 31         /// Initializes a static instance of the Nop factory.
 32
 33         /// 初始化静态Nop工厂的实例
 34
 35         /// </summary>
 36
 37         /// <param name="forceRecreate">创建一个新工厂实例,尽管工厂已经被初始化</param>
 38
 39         [MethodImpl(MethodImplOptions.Synchronized)]
 40
 41         public static IEngine Initialize(bool forceRecreate)
 42
 43         {
 44
 45             if (Singleton<IEngine>.Instance == null || forceRecreate)
 46
 47             {
 48
 49                 Singleton<IEngine>.Instance = new NopEngine();
 50
 51
 52
 53                 var config = ConfigurationManager.GetSection("NopConfig") as NopConfig;
 54
 55                 Singleton<IEngine>.Instance.Initialize(config);
 56
 57             }
 58
 59             return Singleton<IEngine>.Instance;
 60
 61         }
 62
 63
 64
 65         /// <summary>
 66
 67         /// Sets the static engine instance to the supplied engine. Use this method to supply your own engine implementation.
 68
 69         /// 设置静态引擎实例提供的引擎,
 70
 71         /// </summary>
 72
 73         /// <param name="engine">The engine to use.</param>
 74
 75         /// <remarks>Only use this method if you know what you‘re doing.</remarks>
 76
 77         public static void Replace(IEngine engine)
 78
 79         {
 80
 81             Singleton<IEngine>.Instance = engine;
 82
 83         }
 84
 85
 86
 87         #endregion
 88
 89
 90
 91         #region Properties
 92
 93
 94
 95         /// <summary>
 96
 97         /// Gets the singleton Nop engine used to access Nop services.
 98
 99         /// </summary>
100
101         public static IEngine Current
102
103         {
104
105             get
106
107             {
108
109                 if (Singleton<IEngine>.Instance == null)
110
111                 {
112
113                     Initialize(false);
114
115                 }
116
117                 return Singleton<IEngine>.Instance;
118
119             }
120
121         }
122
123
124
125         #endregion
126
127     }
128
129 }

上面Initialize方法使用[MethodImpl(MethodImplOptions.Synchronized)]声明,就保证只能有一个线程访问,因为.NET的Web程序无论是WebForm还是mvc都在服务端都是多线程的。这样就标记只能有一个线程调用Initialize方法,也就保证了实例对象IEngine的在内存中只有一份。然后把单例实例对象的存储到类Singleton中。Singleton就像是一个对象容器,可以把许多单例实例对象存储在里面。

下面我们来看看实例Singleton的实现思路。

二、Singleton

  1 using System;
  2
  3 using System.Collections.Generic;
  4
  5
  6
  7 namespace Nop.Core.Infrastructure
  8
  9 {
 10
 11     /// <summary>
 12
 13     /// A statically compiled "singleton" used to store objects throughout the
 14
 15     /// lifetime of the app domain. Not so much singleton in the pattern‘s
 16
 17     /// sense of the word as a standardized way to store single instances.
 18
 19     /// </summary>
 20
 21     /// <typeparam name="T">The type of object to store.</typeparam>
 22
 23     /// <remarks>Access to the instance is not synchrnoized.</remarks>
 24
 25     public class Singleton<T> : Singleton
 26
 27     {
 28
 29         static T instance;
 30
 31
 32
 33         /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this object for each type of T.</summary>
 34
 35         public static T Instance
 36
 37         {
 38
 39             get { return instance; }
 40
 41             set
 42
 43             {
 44
 45                 instance = value;
 46
 47                 AllSingletons[typeof(T)] = value;
 48
 49             }
 50
 51         }
 52
 53     }
 54
 55
 56
 57     /// <summary>
 58
 59     /// Provides a singleton list for a certain type.
 60
 61     /// </summary>
 62
 63     /// <typeparam name="T">The type of list to store.</typeparam>
 64
 65     public class SingletonList<T> : Singleton<IList<T>>
 66
 67     {
 68
 69         static SingletonList()
 70
 71         {
 72
 73             Singleton<IList<T>>.Instance = new List<T>();
 74
 75         }
 76
 77
 78
 79         /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this list for each type of T.</summary>
 80
 81         public new static IList<T> Instance
 82
 83         {
 84
 85             get { return Singleton<IList<T>>.Instance; }
 86
 87         }
 88
 89     }
 90
 91
 92
 93     /// <summary>
 94
 95     /// Provides a singleton dictionary for a certain key and vlaue type.
 96
 97     /// </summary>
 98
 99     /// <typeparam name="TKey">The type of key.</typeparam>
100
101     /// <typeparam name="TValue">The type of value.</typeparam>
102
103     public class SingletonDictionary<TKey, TValue> : Singleton<IDictionary<TKey, TValue>>
104
105     {
106
107         static SingletonDictionary()
108
109         {
110
111             Singleton<Dictionary<TKey, TValue>>.Instance = new Dictionary<TKey, TValue>();
112
113         }
114
115
116
117         /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this dictionary for each type of T.</summary>
118
119         public new static IDictionary<TKey, TValue> Instance
120
121         {
122
123             get { return Singleton<Dictionary<TKey, TValue>>.Instance; }
124
125         }
126
127     }
128
129
130
131     /// <summary>
132
133     /// Provides access to all "singletons" stored by <see cref="Singleton{T}"/>.
134
135     /// </summary>
136
137     public class Singleton
138
139     {
140
141         static Singleton()
142
143         {
144
145             allSingletons = new Dictionary<Type, object>();
146
147         }
148
149
150
151         static readonly IDictionary<Type, object> allSingletons;
152
153
154
155         /// <summary>Dictionary of type to singleton instances.</summary>
156
157         public static IDictionary<Type, object> AllSingletons
158
159         {
160
161             get { return allSingletons; }
162
163         }
164
165     }
166
167 }

Singleton类里面用一个Dictionary<Type, object>()集合来存储所有的单例对象。基于Singleton类创建一些泛型类Singleton<T>,Singleton<IList<T>>,SingletonList<T>,Singleton<IDictionary<TKey, TValue>>和SingletonDictionary<TKey, TValue>。

时间: 2025-01-03 05:34:28

【NopCommerce源码架构学习-二】单例模式实现代码分析的相关文章

NopCommerce源码架构详解--初识高性能的开源商城系统cms

很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从中学习很多企业系统.软件开发的规范和一些新的技术.技巧,可以快速地提高我们的技术能力.所以我最近决定写一个“NopCommerce源码架构详解”的系列,来详细剖析NopCommerce的架构和原理. Nopcommerce主要用到的技术及特点: 1.Entity Framework 2.ASP.NET mvc 3.IoC容器+依赖注入(Autofac) 4.使用EF中的E

NopCommerce源码架构详解

NopCommerce源码架构详解--初识高性能的开源商城系统cms 很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从中学习很多企业系统.软件开发的规范和一些新的技术.技巧,可以快速地提高我们的技术能力.所以我最近决定写一个“NopCommerce源码架构详解”的系列,来详细剖析NopCommerce的架构和原理. Nopcommerce主要用到的技术及特点: 1.Entity Framework 2.ASP.NET 

Nop--NopCommerce源码架构详解专题目录

最近在研究外国优秀的ASP.NET mvc电子商务网站系统NopCommerce源码架构.这个系统无论是代码组织结构.思想及分层都值得我们学习.对于没有一定开发经验的人要完全搞懂这个源码还是有一定的难度的,所以也打算写一个跟蓝狐学习Nop--NopCommerce源码架构详解系列文章. 以下文章主要针对NopCommerce版本:Nop3.4 NopCommerce源码架构详解--初识高性能的开源商城系统cms NopCommerce源码架构详解--Autofac依赖注入分析 NopCommer

从源码中学习设计模式系列——单例模式序/反序列化以及反射攻击的问题(二)

一.前言 这篇文章是学习单例模式的第二篇,之前的文章一下子就给出来看起来很高大上的实现方法,但是这种模式还是存在漏洞的,具体有什么问题,大家可以停顿一会儿,思考一下.好了,不卖关子了,下面我们来看看每种单例模式存在的问题以及解决办法. 二.每种Singleton 模式的演进 模式一 public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { }

Volley框架源码浅析(二)

尊重原创 http://write.blog.csdn.net/postedit/25921795 在前面的一片文章Volley框架浅析(一)中我们知道在RequestQueue这个类中,有两个队列:本地队列和网络队列 /** The cache triage queue. */ private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<

【原】SDWebImage源码阅读(二)

[原]SDWebImage源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 解决上一篇遗留的坑 上一篇中对sd_setImageWithURL函数简单分析了一下,还留了一些坑.不过因为我们现在对这个函数有一个大概框架了,我们就按顺序一个个来解决. 首先是这一句代码: objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 就是给UIImageVi

Caddy源码阅读(二)启动流程与 Event 事件通知

Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy Caddy 整个软件可以说是由不同的 插件 堆砌起来的.自己本身仅提供 Plugin 的注册运行逻辑和 Server 的监听服务功能. 学习 caddy 的源码,实际上是学习 如何构建一个 松耦合的 抽象 Plugin 设计,即模块化插拔的做法. 所以我们的源码阅读,围绕 Caddy 为 Plugin

跟大家聊聊我们为什么要学习源码?学习源码对我们有用吗?(源码感悟)

1 前言 由于现在微服务很流行,越来越多企业采用了SpringCloud微服务架构,而SpringBoot则是快速构建微服务项目的利器.于是源码笔记以此为切入点,将SpringBoot作为我们源码分析的第一个开源项目,之后还会对更多开源项目进行源码分析.要进行源码分析,笔者结合自身经历来跟大家聊聊我们为什么要学习源码这个话题,大家一起探讨学习. 我们程序员在开发代码时每天都在使用别人写好的框架,无论你是在使用Spring生态的Spring核心,SpringMVC,SpringBoot和Sprin

hbase源码系列(二)HTable 如何访问客户端

hbase的源码终于搞一个段落了,在接下来的一个月,着重于把看过的源码提炼一下,对一些有意思的主题进行分享一下.继上一篇讲了负载均衡之后,这一篇我们从client开始讲吧,从client到master再到region server,按照这个顺序来开展,网友也可以对自己感兴趣的部分给我留言或者直接联系我的QQ. 现在我们讲一下HTable吧,为什么讲HTable,因为这是我们最常见的一个类,这是我们对hbase中数据的操作的入口. 1.Put操作 下面是一个很简单往hbase插入一条记录的例子.