繁体   English   中英

如何在C#中实现一个singleton?

[英]How to implement a singleton in C#?

如何在 C# 中实现 singleton 模式? 我想把我的常量和一些基本函数放在里面,因为我在我的项目中到处都用到它们。 我想让它们“全局”,而不需要在我创建的每个 object 上手动绑定它们。

如果您只是存储一些全局值并且有一些不需要状态的方法,则不需要单例。 只需将类及其属性/方法设为静态即可。

public static class GlobalSomething
{
   public static int NumberOfSomething { get; set; }

   public static string MangleString( string someValue )
   {
   }
}

当你有一个普通的有状态的类时,单例是最有用的,但你只想要其中一个。 其他人提供的链接对于探索单例模式应该很有用。

Singleton != Global 您似乎正在寻找关键字static

只有当这两个条件都为真时,单例才有意义:

  1. 对象必须是全局的
  2. 有只必须时刻存在对象的单个实例

请注意,#2,并不意味着你想要的对象只有一个实例-如果多数民众赞成的情况下,简单地初始化它只有一次-这意味着必须有(如,这是危险的,这是不正确的)只能是一个实例。

如果您想要全局,只需创建某个(非符号)对象的全局实例(或使其成为静态或其他)。 如果您只想要一个实例,那么静态是您的朋友。 此外,只需实例化一个对象。

反正这是我的意见。

您可以真正简化单例实现,这就是我使用的:

    internal FooService() { }        
    static FooService() { }

    private static readonly FooService _instance = new FooService();

    public static FooService Instance
    {
        get { return _instance; }
    }

嗯,这一切似乎有点复杂。

为什么需要依赖注入框架来获取单例? 对于某些企业应用程序来说,使用 IOC 容器是可以的(当然,只要它没有被过度使用),但是,啊,这家伙只是想知道如何实现该模式。

为什么不总是急切地实例化,然后提供一个返回静态的方法,上面写的大部分代码然后就消失了。 遵循古老的 C2 格言 - DoTheSimplestThingThatCouldPossiblyWork...

我建议您阅读 MSDN 上提供的Exploring the Singleton Design Pattern文章。 它详细介绍了使模式易于实现的框架的特性。

顺便说一句,我会查看SO 有关 Singletons相关阅读

忽略你是否应该使用单例模式的问题,这已经在别处讨论过,我会像这样实现一个单例:

/// <summary>
/// Thread-safe singleton implementation
/// </summary>
public sealed class MySingleton {

    private static volatile MySingleton instance = null;
    private static object syncRoot = new object();

    /// <summary>
    /// The instance of the singleton
    /// safe for multithreading
    /// </summary>
    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;
        }
    }


    /// <summary>
    /// This constructor must be kept private
    /// only access the singleton through the static Instance property
    /// </summary>
    private MySingleton() {

    }

}

如果您想要松散耦合的设计,静态单例几乎是一种反模式。 尽可能避免,除非这是一个非常简单的系统,否则我建议您查看许多可用的依赖注入框架之一,例如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<Dependency>()))

var container = builder.Build();

var configured = container.Resolve<RequiresDependency>();

顺便说一句,公认的答案是一个糟糕的解决方案,至少检查实际实施该模式的人。

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()
        {
        }
    }

    /// <summary>Private Constructor for Singleton Pattern Implementaion</summary>
    /// <remarks>can be used for initializing member variables</remarks>
    private Globals()
    {

    }

    /// <summary>Returns a reference to the unique instance of Globals class</summary>
    /// <remarks>used for getting a reference of Globals class</remarks>
    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<T> where T : new()
    {
        private static T ms_StaticInstance = new T();

        public T Build()
        {
            return ms_StaticInstance;
        }
    }

...
    GenericSingleton<SimpleType> builder1 = new GenericSingleton<SimpleType>();
    SimpleType simple = builder1.Build();

这将为您提供一个实例(以正确的方式实例化)并且实际上是惰性的,因为在调用 Build() 之前不会调用静态构造函数。

您所描述的只是静态函数和常量,而不是单例。 Singleton设计模式(这是很少需要)描述了实例化,但只有一次,自动,当第一次使用的类。

它将延迟初始化与检查结合起来,以防止多次实例化。 它仅对于包装一些物理上单一的概念的类才真正有用,例如围绕硬件设备的包装器。

静态常量和函数就是这样:根本不需要实例的代码。

问问自己这个问题:“如果有多个实例,这个类会中断吗?” 如果答案是否定的,则不需要单例。

嗯...很少有具有相关功能的常量...通过枚举不是更好吗? 我知道您可以使用方法和所有方法在 Java 中创建自定义枚举,在 C# 中也应该可以实现,如果不直接支持,那么可以使用带有私有构造函数的简单类单例来完成。

如果您的常量在语义上相关,您应该考虑枚举(或等效概念),您将获得 const 静态变量的所有优势 + 您将能够利用编译器的类型检查来发挥您的优势。

我的 2 美分

就我个人而言,我会选择一个依赖注入框架,比如 Unity,它们都能够在容器中配置单例项,并通过从类依赖转移到接口依赖来改善耦合。

通过隐藏公共构造函数,添加一个私有静态字段来保存这个唯一的实例,并添加一个静态工厂方法(带有惰性初始化器)来返回那个单一的实例

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();
    }   
}

我使用单例模式为我的项目编写了一个类。 这是非常容易使用。 希望它对你有用。 请找到以下代码。

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<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}

如何在C#中实现单例模式? 我想在我的项目中到处使用常量和一些基本函数。 我想让它们“全局”,而不需要手动绑定我创建的每个对象。

您可以通过将 static 属性实例(名称可以变化)添加到其中并初始化如下,为您的通用(非静态)class 制作一个简单的手册 static singleton 实现:

public class MyClass
{
    private static MyClass _instance;
    public static MyClass Instance => _instance ?? (_instance = new MyClass());

    // add here whatever constructor and other logic you like or need.
}

然后它可以从这个命名空间的任何地方解析,如下所示:

var myClass = MyClass.Instance;   // without any new keyword
myClass.SomeNonStaticMethod();
// or: 
MyClass.Instance.SomeNonStaticMethod();
// or:
MyClass.Instance.SomeNonStaticProperty = "new value";

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM