Sinfim Initialize usuli faqat bir marta chaqirilsin, qanday qilib eng yaxshi yondashuv bo'lardi?

Hozirda Unity IoC konteyneridan foydalanmoqdaman va bu erda AppConfig mening sinfim. Ko'rib turganingizdek, Initialize usuli faqat bir marta chaqirilishi kerak va men ishonch hosil qilish uchun ikki marta qulflangan tekshiruvdan foydalanganman.

Agar mening yondashuvim eng yaxshi usul bo'lmasa, bunga erishishning eng yaxshi usuli nima bo'ladi?

public interface IAppConfig
{
    /// 
/// Gets the admin username. ///
 
    /// The admin username.
    string AdminUsername { get; }

    /// 
/// Gets the admin password. ///
 
    /// The admin password.
    string AdminPassword { get; }

    /// 
/// Initializes this instance. ///
 
    void Initialize();
}

/// 
/// A singleton App config which helps reading from web.config /// its lifetime is controlled by Unity. ///
 
public class AppConfig : IAppConfig
{
    #region Fields

    /// 
/// the injectable config manager ///
 
    private readonly IConfigManager _configManager;

    private readonly ILogger _logger;

    private static readonly object LockObject = new object();

    private static bool _initialized = false;

    #endregion

    #region Constructors

    /// 
/// Initializes a new instance of the class. ///
 
    public AppConfig(IConfigManager configManager, ILogger logger)
    {
        this._configManager = configManager;
        this._logger = logger;
    }

    #endregion

    #region Properties

    /// 
/// Gets the admin username. ///
 
    /// The admin username.
    public string AdminUsername { get; private set; }

    /// 
/// Gets the admin password. ///
 
    /// The admin password.
    public string AdminPassword { get; private set; }

    #endregion

    #region Methods

    public void Initialize()
    {
        if (_initialized)
        {
            throw new ApplicationException("Initialize method should be called only once");
        }

        lock(LockObject)
        {
            if (_initialized) return;

            var adminUserNameSetting = _configManager.AppSettings[ConfigKeys.AdminUsername];

            if (adminUserNameSetting == null)
            {
                throw new ApplicationException("AdminUsername key not found");
            }

            this.AdminUsername = adminUserNameSetting.Value;

            if (String.IsNullOrWhiteSpace(this.AdminUsername))
            {
                _logger.LogError("AdminUsername not found");
            }

           //log
            var adminPasswordSetting = _configManager.AppSettings[ConfigKeys.AdminPassword];

            if (adminPasswordSetting == null)
            {
                throw new ApplicationException("AdminPassword key not found");
            }

            this.AdminPassword = adminPasswordSetting.Value;

            if (String.IsNullOrWhiteSpace(this.AdminPassword))
            {
                _logger.LogError("AdminPassword not found");
            }
            _initialized = true;
        }
    }

    #endregion
}

Birlikda quyidagi kodni ishlataman:

// IAppConfig
container.RegisterType(new ContainerControlledLifetimeManager(),
                                              new InjectionConstructor(configManager,
                                                                       logger));
var appConfig = container.Resolve();
appConfig.Initialize();
0
Men uni bir marta chaqiraman, biroq uni bir marta emas, balki ikki marta emas, deb xato qilishni xohlayman!
qo'shib qo'ydi muallif The Light, manba
Konstruktordan uni chaqirish bilan bog'liq muammo shundan iboratki, u kamroq bo'linadi.
qo'shib qo'ydi muallif The Light, manba
Nima uchun faqat uni bir marta chaqirmaysiz? Yuqori mudofaa dasturlari orqali bu super bilan nima sodir bo'ladi.
qo'shib qo'ydi muallif Raynos, manba
manba kodining statik tahlili - bu sizning dasturingiz kodini qulflash mexanizmlari bilan parchalash uchun yaxshi echimdir.
qo'shib qo'ydi muallif Raynos, manba
DR., Bu konstruktordan chaqirilsinmi?
qo'shib qo'ydi muallif sll, manba

4 javoblar

Menimcha Initalize() usuli ilova masalasiga o'xshaydi. Bu degani, u interfeysda bo'lmasligi mumkin.

Bir misolni ishga tushirish konstruktorga eng yaxshi deb hisoblanadi.

Agar chindan ham kechiktirilgan Initializatsiya kerak bo'lsa, siz bool bilan yechim va qulflash OK ko'rinadi.

3
qo'shib qo'ydi
Rahmat. Odatda, men konstruktorni toza saqlayman va asosan xususiy ob'ektlarni o'rnatish va boshqa xususiyatlarni hisoblash yoki tasdiqlash yoki boshlash kerak bo'lganda kechiktirilgan boshlashni ishlatish uchun foydalanaman. Dadil Initialization va kechiktirilgan boshlash.
qo'shib qo'ydi muallif The Light, manba
Chunki barcha xususiyatlar birlashtirilgan bo'lishi kerak, shuning uchun dangasa yuklash ishlamaydi. Dastlab men ijobiy ishga tushirishni boshlagan edim, lekin buning sababi tufayli uni ishga tushirishni kechiktirdim deb o'yladim.
qo'shib qo'ydi muallif The Light, manba
Agar boshqa funktsiyalarni hisoblash yoki tasdiqlash kerak yoki keyinroq ni ishga tushirish kerak bo'lsa, nega sinfga qo'ng'iroq kodini emas, balki, bu harakatga g'amxo'rlik qilish uchun bu xususiyatlarga nisbatan dangasa yuklarni qo'llamaysizmi? Bu inkapsulatsiyaning yarmi.
qo'shib qo'ydi muallif Michael Paulukonis, manba

Initialize usulida nima qilayotganingizni ko'rib chiqayapman, deb o'ylayman, siz nima deb o'ylaysiz, bu klassni bir singleton sifatida qayd etib, konteynerni saqlab qolish. Buni bu erda qilish mumkinligini ko'rishingiz mumkin:

http://gunnarpeipman.com/2008/04/unity-and-singletons/

1
qo'shib qo'ydi
Sinfi singleton sifatida allaqachon ro'yxatdan o'tkazganman; kodimni to'g'ri o'qidingizmi?
qo'shib qo'ydi muallif The Light, manba
Aytganimdek, allaqachon singleton! uning umrini Birlik tomonidan nazorat qilinadi.
qo'shib qo'ydi muallif The Light, manba
Agar singleton mening instinktim ham bo'lishi mumkin va ha, u sizning AppConfig klassi davlat quruvchisi tomonidan ko'rsatilgandek C# uchun tekli naqshga rioya qilmasa kodingizni to'g'ri o'qigan.
qo'shib qo'ydi muallif ChrisBD, manba
Uilyam, siz to'g'ri.
qo'shib qo'ydi muallif David Savage, manba

Yaxshilab, siz "Birlik" ga ishonchingiz komil. C# uchun kod tuzilishi juda oson bo'lsa ham. bu yerda ko'ring. Keyinchalik konstruktorda boshlang'ich kodini chaqiring.

Har qanday holatda kodni atmo holatida turganingizdagina, sizning boshlash bayrog'ingizni o'zgartiraman.

0
qo'shib qo'ydi
Vulqonni ishlatmaslik sababi, men ikki marta tekshiruvdan foydalanganim sababli kerak emas. Favqulodda bir ish zarrachalar boshqa bir ish zarrachasi tomonidan yozilgan eng dolzarb qiymatni oladi va kod hech qanday o'zgaruvchanlikni ta'minlaydi.
qo'shib qo'ydi muallif The Light, manba

Men qabul qiluvchi qurilmada ishga tushirilganligini tekshiradigan statik sinfi misol o'zgaruvchiga ega bo'lishni afzal ko'raman. Sinovga namuna xususiyati orqali kiring va sinfning necha marta ishga tushirilishini nazorat qilasiz. Bu aslida standart C# singleton naqshidir:

public static class MySingleton 
{
    private static Mutex instanceLock = new Mutex();

    private static MySingleton instance;
    public static MySingleton Instance
    {
        get
        {
            instanceLock.WaitOne();
            if(instance == null)
            {
                instance = new MySingleton();
            }
            instanceLock.ReleaseMutex();
            return instance;
         }
    }

    private MySingleton()
    {
        Initialize();
    }

    private void Initialize()
    {
       //Initialize
    }
}

public class MyOtherClass
{
    private MySingleton singleton = MySingleton.Instance;
}
0
qo'shib qo'ydi