简体   繁体   English

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

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

How do I implement the singleton pattern in C#?如何在 C# 中实现 singleton 模式? I want to put my constants and some basic functions in it as I use those everywhere in my project.我想把我的常量和一些基本函数放在里面,因为我在我的项目中到处都用到它们。 I want to have them 'Global' and not need to manually bind them every object I create.我想让它们“全局”,而不需要在我创建的每个 object 上手动绑定它们。

If you are just storing some global values and have some methods that don't need state, you don't need singleton.如果您只是存储一些全局值并且有一些不需要状态的方法,则不需要单例。 Just make the class and its properties/methods static.只需将类及其属性/方法设为静态即可。

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

   public static string MangleString( string someValue )
   {
   }
}

Singleton is most useful when you have a normal class with state, but you only want one of them.当你有一个普通的有状态的类时,单例是最有用的,但你只想要其中一个。 The links that others have provided should be useful in exploring the Singleton pattern.其他人提供的链接对于探索单例模式应该很有用。

Singleton != Global . Singleton != Global You seem to be looking for the keyword static .您似乎正在寻找关键字static

Singletons only make sense if both of these conditions are true:只有当这两个条件都为真时,单例才有意义:

  1. The object must be global对象必须是全局的
  2. There must only ever exist a single instance of the object有只必须时刻存在对象的单个实例

Note that #2 does not mean that you'd like the object to only have a single instance - if thats the case, simply instantiate it only once - it means that there must (as in, it's dangerous for this not to be true) only ever be a single instance.请注意,#2,并不意味着你想要的对象只有一个实例-如果多数民众赞成的情况下,简单地初始化它只有一次-这意味着必须有(如,这是危险的,这是不正确的)只能是一个实例。

If you want global, just make a global instance of some (non signleton) object (or make it static or whatever).如果您想要全局,只需创建某个(非符号)对象的全局实例(或使其成为静态或其他)。 If you want only one instance, again, static is your friend.如果您只想要一个实例,那么静态是您的朋友。 Also, simply instantiate only one object.此外,只需实例化一个对象。

Thats my opinion anyway.反正这是我的意见。

You can really simplify a singleton implementation, this is what I use:您可以真正简化单例实现,这就是我使用的:

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

    private static readonly FooService _instance = new FooService();

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

Hmm, this all seems a bit complex.嗯,这一切似乎有点复杂。

Why do you need a dependency injection framework to get a singleton?为什么需要依赖注入框架来获取单例? Using an IOC container is fine for some enterprise app (as long as it's not overused, of course), but, ah, the fella just wants to know about implementing the pattern.对于某些企业应用程序来说,使用 IOC 容器是可以的(当然,只要它没有被过度使用),但是,啊,这家伙只是想知道如何实现该模式。

Why not always eagerly instantiate, then provide a method that returns the static, most of the code written above then goes away.为什么不总是急切地实例化,然后提供一个返回静态的方法,上面写的大部分代码然后就消失了。 Follow the old C2 adage - DoTheSimplestThingThatCouldPossiblyWork...遵循古老的 C2 格言 - DoTheSimplestThingThatCouldPossiblyWork...

I would recommend you read the article Exploring the Singleton Design Pattern available on MSDN.我建议您阅读 MSDN 上提供的Exploring the Singleton Design Pattern文章。 It details the features of the framework which make the pattern simple to implement.它详细介绍了使模式易于实现的框架的特性。

As an aside, I'd check out the related reading on SO regarding Singletons .顺便说一句,我会查看SO 有关 Singletons相关阅读

Ignoring the issue of whether or not you should be using the Singleton pattern, which has been discussed elsewhere, I would implement a singleton like this:忽略你是否应该使用单例模式的问题,这已经在别处讨论过,我会像这样实现一个单例:

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

    }

}

Static singleton is pretty much an anti pattern if you want a loosely coupled design.如果您想要松散耦合的设计,静态单例几乎是一种反模式。 Avoid if possible, and unless this is a very simple system I would recommend having a look at one of the many dependency injection frameworks available, such as http://ninject.org/ or http://code.google.com/p/autofac/ .尽可能避免,除非这是一个非常简单的系统,否则我建议您查看许多可用的依赖注入框架之一,例如http://ninject.org/http://code.google.com/p /autofac/

To register / consume a type configured as a singleton in autofac you would do something like the following:要在 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>();

The accepted answer is a terrible solution by the way, at least check the chaps who actually implemented the pattern.顺便说一句,公认的答案是一个糟糕的解决方案,至少检查实际实施该模式的人。

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

}

I like this pattern, although it doesn't prevent someone from creating a non-singleton instance.我喜欢这种模式,尽管它不会阻止某人创建非单例实例。 It can sometimes can be better to educate the developers in your team on using the right methodology vs. going to heroic lengths to prevent some knucklehead from using your code the wrong way...有时,最好教育团队中的开发人员使用正确的方法,而不是竭尽全力防止某些笨蛋以错误的方式使用您的代码……

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

This will give you a single instance (instantiated the right way) and will effectively be lazy, because the static constructor doesn't get called until Build() is called.这将为您提供一个实例(以正确的方式实例化)并且实际上是惰性的,因为在调用 Build() 之前不会调用静态构造函数。

What you are describing is merely static functions and constants, not a singleton.您所描述的只是静态函数和常量,而不是单例。 The singleton design pattern (which is very rarely needed) describes a class that is instantiated, but only once, automatically, when first used. Singleton设计模式(这是很少需要)描述了实例化,但只有一次,自动,当第一次使用的类。

It combines lazy initialization with a check to prevent multiple instantiation.它将延迟初始化与检查结合起来,以防止多次实例化。 It's only really useful for classes that wrap some concept that is physically singular, such as a wrapper around a hardware device.它仅对于包装一些物理上单一的概念的类才真正有用,例如围绕硬件设备的包装器。

Static constants and functions are just that: code that doesn't need an instance at all.静态常量和函数就是这样:根本不需要实例的代码。

Ask yourself this: "Will this class break if there is more than one instance of it?"问问自己这个问题:“如果有多个实例,这个类会中断吗?” If the answer is no, you don't need a singleton.如果答案是否定的,则不需要单例。

hmmm... Few constants with related functions... would that not better be achieved through enums ?嗯...很少有具有相关功能的常量...通过枚举不是更好吗? I know you can create a custom enum in Java with methods and all, the same should be attainable in C#, if not directly supported then can be done with simple class singleton with private constructor.我知道您可以使用方法和所有方法在 Java 中创建自定义枚举,在 C# 中也应该可以实现,如果不直接支持,那么可以使用带有私有构造函数的简单类单例来完成。

If your constants are semantically related you should considered enums (or equivalent concept) you will gain all advantages of the const static variables + you will be able to use to your advantage the type checking of the compiler.如果您的常量在语义上相关,您应该考虑枚举(或等效概念),您将获得 const 静态变量的所有优势 + 您将能够利用编译器的类型检查来发挥您的优势。

My 2 cent我的 2 美分

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

By hiding public constructor, adding a private static field to hold this only instance, and adding a static factory method (with lazy initializer) to return that single instance通过隐藏公共构造函数,添加一个私有静态字段来保存这个唯一的实例,并添加一个静态工厂方法(带有惰性初始化器)来返回那个单一的实例

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

I have written a class for my project using Singleton pattern.我使用单例模式为我的项目编写了一个类。 It is very easy to use.这是非常容易使用。 Hope it will work for you.希望它对你有用。 Please find the code following.请找到以下代码。

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

Now you can set variable value for the above code in your application like this..现在您可以像这样在应用程序中为上述代码设置变量值。

[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");
}

And you can retrieve those value like this..你可以像这样检索这些值..

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

In c# it could be (Thread safe as well as lazy initialization):在 c# 中它可能是(线程安全以及延迟初始化):

public sealed class MySingleton
{
    static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}

How do I implement the singleton pattern in C#?如何在C#中实现单例模式? I want to put my constants and some basic functions in it as I use those everywhere in my project.我想在我的项目中到处使用常量和一些基本函数。 I want to have them 'Global' and not need to manually bind them every object I create.我想让它们“全局”,而不需要手动绑定我创建的每个对象。

You can make a simple manual static singleton implementation for your common (non-static) class by adding a static property Instance (name can vary) into it with initialization like this:您可以通过将 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.
}

Then it can be resolved anywhere from this namespace like this:然后它可以从这个命名空间的任何地方解析,如下所示:

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