سؤال

كيف يمكنني تنفيذ النمط المفرد في C#؟أريد أن أضع ثوابتي وبعض الوظائف الأساسية فيه حيث أستخدمها في كل مكان في مشروعي.أريد أن أجعلها "عامة" ولا أحتاج إلى ربطها يدويًا بكل كائن أقوم بإنشائه.

هل كانت مفيدة؟

المحلول

إذا كنت مجرد تخزين بعض القيم العالمية وبعض الأساليب التي لا تحتاج الدولة، لا تحتاج المفرد. فقط تأكد الطبقة وخصائصه / طرق ثابتة.

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

   public static string MangleString( string someValue )
   {
   }
}

والمفرد هو أكثر فائدة عندما يكون لديك فئة طبيعية مع الدولة، ولكن كنت تريد واحدة منها فقط. الارتباطات التي قدمت الآخرين ينبغي أن يكون مفيدا في استكشاف نمط سينغلتون.

نصائح أخرى

وSingleton != Global. يبدو أنك تبحث عن static الكلمة.

المفردات تكون منطقية فقط إذا كلاهما من هذه الشروط صحة:

  1. يجب أن يكون الكائن عالمي
  2. يجب أن يكون هناك فقط أ أعزب مثيل الكائن

لاحظ أن الرقم 2 لا يعني أنك ستفعل ذلك يحب أن يكون للكائن مثيل واحد فقط - إذا كان الأمر كذلك، فما عليك سوى إنشاء مثيل له مرة واحدة فقط - فهذا يعني أن هناك يجب (كما هو الحال في أنه من الخطورة ألا يكون هذا صحيحًا) لا تكون سوى حالة واحدة.

إذا كنت تريد عموميًا، فما عليك سوى إنشاء مثيل عالمي لبعض الكائنات (بدون إشارة) (أو اجعله ثابتًا أو أيًا كان).إذا كنت تريد مثيلًا واحدًا فقط، فمرة أخرى، static هو صديقك.بالإضافة إلى ذلك، قم ببساطة بإنشاء كائن واحد فقط.

وهذا رأيي على أي حال.

ويمكنك تبسيط حقا تنفيذ المفرد، وهذا هو ما يمكنني استخدام:

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

    private static readonly FooService _instance = new FooService();

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

وهم، كل هذا يبدو معقدة بعض الشيء.

وماذا كنت في حاجة الى إطار حقن التبعية للحصول على المفرد؟ باستخدام حاوية اللجنة الأولمبية الدولية على ما يرام بالنسبة لبعض التطبيقات المشاريع، (طالما انها لا يبالغ طبعا)، ولكن، آه، وفيلا يريد فقط أن نعرف aboiut تنفيذ النمط.

لماذا لا مثيل دائما بفارغ الصبر، ثم توفير أسلوب بإرجاع ثابت، ومعظم من قانون مكتوب أعلاه ثم يذهب بعيدا. اتبع C2 القول المأثور القديم - DoTheSimplestThingThatCouldPossiblyWork ...

وتجاهل مسألة ما إذا كان أو لا يجب أن تستخدم نمط سينغلتون، الذي تمت مناقشته في أي مكان آخر، وأود أن تنفيذ المفرد مثل هذا:

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

    }

}

وثابت المفرد هو الى حد كبير نمط مكافحة إذا كنت ترغب في تصميم المتباعدة. تجنب إذا أمكن، وإلا إذا كان هذا هو نظام بسيط جدا أوصي وجود نظرة على واحدة من العديد من أطر حقن التبعية المتاحة، مثل <وأ href = "http://ninject.org/" يختلط = "نوفولو noreferrer" > http://ninject.org/ أو http://code.google.com / ص / 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); }
    }

}

وأنا أحب هذا النمط، على الرغم من أنه لا يمنع أي شخص من إنشاء مثيل غير المفرد. ويمكن في بعض الأحيان يمكن أن يكون أفضل لتثقيف المطورين في فريقك على استخدام حق مقابل منهجية الذهاب إلى أبعد بطولية لمنع بعض knucklehead من استخدام التعليمات البرمجية بطريقة خاطئة ...

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

وهذا سوف أعطيك نسخة واحدة (مثيل في الطريق الصحيح)، وسوف يكون على نحو فعال كسول، لأن المنشئ ثابت لا الحصول على استدعاء حتى يتم استدعاء إنشاء ().

ما كنت تصف هو مجرد وظائف والثوابت ثابتة، <م> لا عن المفردة. نمط تصميم المفرد (التي نادرا ما الحاجة) يصف فئة <م> هو مثيل، ولكن مرة واحدة فقط، تلقائيا، عندما استخدم لأول مرة.

فهو يجمع بين التهيئة كسول مع شيك لمنع مثيل متعددة. انها فقط مفيدة حقا للفئات التي التفاف بعض المفهوم الذي هو المفرد جسديا، مثل مجمع حول الجهاز.

والثوابت وظائف ثابتة ليست سوى ذلك: التعليمات البرمجية التي لا تحتاج مثيل على الإطلاق

واسأل نفسك: "هل هذا الكسر الدرجة إذا كان هناك أكثر من مثيل واحد من ذلك؟" إذا كان الجواب لا، أنت لا تحتاج إلى المفرد.

وهممم ... قليل من الثوابت مع المهام ذات الصلة ... فإن ذلك لم يكن أفضل أن يتحقق من خلال تتضمن التعدادات؟ وأنا أعلم أنك يمكن أن تخلق التعداد العرف في جاوة مع الأساليب وقبل كل شيء، يجب أن تكون هي نفسها يمكن بلوغه في C #، إن لم يكن دعما مباشرا ثم يمكن القيام به مع المفرد الدرجة بسيط مع منشئ الخاص.

إذا ترتبط الثوابت الخاصة غويا يجب أن يعتبر تتضمن التعدادات (أو مفهوم ما يعادلها) سوف تكسب أنت حسنات عن مزايا المتغيرات ثابتة CONST + سوف تكون قادرة على استخدامها لصالحك نوع التحقق من المجمع.

وبلدي 2 المائة

وأنا شخصيا أود أن أذهب إلى إطار حقن التبعية، مثل الوحدة، كل منهم قادرا على تكوين العناصر المفردة في حاوية ومن شأنه أن يحسن اقتران بالانتقال من تبعية الطبقة إلى واجهة التبعية.

وبالاختباء منشئ العام، إضافة حقل ثابت الخاص لعقد هذه الحالة فقط، وإضافة وسيلة مصنع ثابت (مع مهيئ كسول) للعودة أن مثيل واحد

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

في ج # يمكن أن يكون (الموضوع تهيئة آمنة وكذلك كسول):

public sealed class MySingleton
{
    static volatile Lazy<MySingleton> _instance = new Lazy<MySingleton>(() => new MySingleton(), true);
    public static MySingleton Instance => _instance.Value;
    private MySingleton() { }
}
public class Singleton
{
   private static Singleton _instance;
   public static Singleton Instance => _instance ?? (_instance = new Singleton());
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top