如何在C#中实现单例?
如何在C#中实现单例模式? 我想把我的常量和一些基本function放在其中,因为我在项目的每个地方使用它们。 我希望将它们设置为“全局”,而不需要为我创建的每个对象手动绑定它们。
如果您只是存储一些全局值并且有一些不需要状态的方法,则不需要单例。 只需使类及其属性/方法保持静态。
public static class GlobalSomething { public static int NumberOfSomething { get; set; } public static string MangleString( string someValue ) { } }
当你有一个普通的有状态的类时,单例是最有用的,但你只需要其中一个。 其他人提供的链接应该有助于探索Singleton模式。
Singleton != Global
。 您似乎在寻找关键字static
。
你可以真正简化单例实现,这就是我使用的:
internal FooService() { } static FooService() { } private static readonly FooService _instance = new FooService(); public static FooService Instance { get { return _instance; } }
嗯,这一切似乎有点复杂。
为什么需要dependency injection框架才能获得单例? 对于某些企业应用程序来说,使用IOC容器是好的(只要它当然没有被过度使用),但是,啊,这个家伙只是想知道实现该模式的方法。
为什么不总是急切地实例化,然后提供一个返回静态的方法,然后上面写的大部分代码都消失了。 按照旧的C2格言 – DoTheSimplestThingThatCouldPossiblyWork …
如果这两个条件都成立,单身人士才有意义:
- 对象必须是全局的
- 必须只存在该对象的单个实例
请注意,#2并不意味着您希望对象只有一个实例 – 如果是这种情况,只需将其实例化一次 – 这意味着必须 (因为,这样做不危险)只是一个单一的实例。
如果你想要全局,只需创建一些(非符号)对象的全局实例(或使其成为静态或其他)。 如果你只想要一个实例,那么static就是你的朋友。 此外,只需实例化一个对象。
无论如何,这是我的意见。
我建议你阅读MSDN上提供的探索Singleton设计模式的文章。 它详细介绍了框架的function,使模式易于实现。
顺便说一句,我会查看关于单身人士的相关阅读材料 。
忽略你是否应该使用Singleton模式的问题,这已在别处讨论过,我会实现这样的单例:
/// /// Thread-safe singleton implementation /// public sealed class MySingleton { private static volatile MySingleton instance = null; private static object syncRoot = new object(); /// /// The instance of the singleton /// safe for multithreading /// public static MySingleton Instance { get { // only create a new instance if one doesn't already exist. if (instance == null) { // use this lock to ensure that only one thread can access // this block of code at once. lock (syncRoot) { if (instance == null) { instance = new MySingleton(); } } } // return instance where it was just created or already existed. return instance; } } /// /// This constructor must be kept private /// only access the singleton through the static Instance property /// private MySingleton() { } }
如果你想要一个松散耦合的设计,静态单例几乎是一种反模式。 如果可能的话,尽量避免,除非这是一个非常简单的系统,否则我建议您查看可用的许多dependency injection框架之一,例如http://ninject.org/或http://code.google.com/p / autofac / 。
要注册/使用在autofac中配置为单例的类型,您可以执行以下操作:
var builder = new ContainerBuilder() builder.Register(typeof(Dependency)).SingletonScoped() builder.Register(c => new RequiresDependency(c.Resolve())) var container = builder.Build(); var configured = container.Resolve();
顺便说一句,接受的答案是一个可怕的解决方案,至少检查实际实现模式的人。
public class Globals { private string setting1; private string setting2; #region Singleton Pattern Implementation private class SingletonCreator { internal static readonly Globals uniqueInstance = new Globals(); static SingletonCreator() { } } /// Private Constructor for Singleton Pattern Implementaion /// can be used for initializing member variables private Globals() { } /// Returns a reference to the unique instance of Globals class /// used for getting a reference of Globals class public static Globals GetInstance { get { return SingletonCreator.uniqueInstance; } } #endregion public string Setting1 { get { return this.setting1; } set { this.setting1 = value; } } public string Setting2 { get { return this.setting2; } set { this.setting2 = value; } } public static int Constant1 { get { reutrn 100; } } public static int Constat2 { get { return 200; } } public static DateTime SqlMinDate { get { return new DateTime(1900, 1, 1, 0, 0, 0); } } }
我喜欢这种模式,虽然它不会阻止某人创建非单例实例。 有时可以更好地教育团队中的开发人员使用正确的方法而不是英雄的长度,以防止某些傻瓜以错误的方式使用您的代码……
public class GenericSingleton where T : new() { private static T ms_StaticInstance = new T(); public T Build() { return ms_StaticInstance; } } ... GenericSingleton builder1 = new GenericSingleton (); SimpleType simple = builder1.Build();
这将为您提供单个实例(以正确方式实例化)并且实际上将是惰性的,因为在调用Build()之前不会调用静态构造函数。
你所描述的仅仅是静态函数和常量, 而不是单例。 单例设计模式(很少需要)描述了一个实例化的类,但在首次使用时只能自动执行一次。
它结合了延迟初始化和检查以防止多次实例化。 它只对包含一些物理上单一的概念的类非常有用,例如硬件设备周围的包装器。
静态常量和函数就是:完全不需要实例的代码。
问问自己:“如果有一个以上的实例,这个课程会破裂吗?” 如果答案是否定的,则不需要单身人士。
嗯…很少有相关function的常量……通过枚举会不会更好? 我知道你可以使用方法和所有方法在Java中创建自定义枚举,在C#中也应该可以实现,如果不是直接支持,那么可以使用私有构造函数的简单类单例来完成。
如果您的常量在语义上相关,那么您应该考虑枚举(或等效概念),您将获得const静态变量的所有优点+您将能够利用编译器的类型检查。
我的2美分
我个人会选择像Unity一样的dependency injection框架,它们都能够在容器中配置单例项,并通过从类依赖转移到接口依赖来改善耦合。
通过隐藏公共构造函数,添加一个私有静态字段来保存这个唯一的实例,并添加一个静态工厂方法(使用惰性初始化程序)来返回该单个实例
public class MySingleton { private static MySingleton sngltn; private static object locker; private MySingleton() {} // Hides parameterless ctor, inhibits use of new() public static MySingleton GetMySingleton() { lock(locker) return sngltn?? new MySingleton(); } }
我使用Singleton模式为我的项目编写了一个类。 这是非常容易使用。 希望它对你有用。 请找到以下代码。
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace TEClaim.Models { public class LogedinUserDetails { public string UserID { get; set; } public string UserRole { get; set; } public string UserSupervisor { get; set; } public LogedinUserDetails() { } public static LogedinUserDetails Singleton() { LogedinUserDetails oSingleton; if (null == System.Web.HttpContext.Current.Session["LogedinUserDetails"]) { oSingleton = new LogedinUserDetails(); System.Web.HttpContext.Current.Session["LogedinUserDetails"] = oSingleton; } else { oSingleton = (LogedinUserDetails)System.Web.HttpContext.Current.Session["LogedinUserDetails"]; } //Return the single instance of this class that was stored in the session return oSingleton; } } }
现在您可以像这样在应用程序中为上面的代码设置变量值。
[HttpPost] public ActionResult Login(FormCollection collection) { LogedinUserDetails User_Details = LogedinUserDetails.Singleton(); User_Details.UserID = "12"; User_Details.UserRole = "SuperAdmin"; User_Details.UserSupervisor = "815978"; return RedirectToAction("Dashboard", "Home"); }
你可以像这样检索那些值..
public ActionResult Dashboard() { LogedinUserDetails User_Details = LogedinUserDetails.Singleton(); ViewData["UserID"] = User_Details.UserID; ViewData["UserRole"] = User_Details.UserRole; ViewData["UserSupervisor"] = User_Details.UserSupervisor; return View(); }
在c#中它可能是(线程安全以及延迟初始化):
public sealed class MySingleton { static volatile Lazy _instance = new Lazy (() => new MySingleton(), true); public static MySingleton Instance => _instance.Value; private MySingleton() { } }