簡體   English   中英

SharePoint Web部件和單例

[英]SharePoint Web Part & Singletons

我有一個共享項目,我們在其中覆蓋搜索框和其他一些東西。 我們還有一個Web部件頁面,可響應搜索框。 所有這些組件應共享一個配置。 我曾考慮過要創建一個單例,但不確定如何從內存中清除/刪除/卸載。

有任何想法嗎? 關於在共享點中使用單例的任何警告? 另外,是否存在在所有這些組件網絡之間共享對象實例的適當方法?

編輯:我正在考慮一個非常簡單的單例。 配置最多只需要包含5-20個字符串和12個整數。 沒有復雜的對象:)

只要由您的singleton類管理的對象是線程安全的,就不會有問題。

例:
我有一系列的對象調用需要很長時間才能處理(7+秒)。 因此,我決定嘗試使用彗星風格的長輪詢技術來處理它們。 這樣,我在單個線程中托管了一個服務(作為靜態單例),並使用異步HttpHandler來處理請求...並且效果很好! 而且由於我異步使用服務,所以它的效率很高,因為調用線程會立即釋放(處理完服務后會完成回調)。

編輯:
但是仍然存在處理時間長的問題,因此您(可能)仍需要異步解決方案來進行初始提取。 這個怎么樣? 為什么不將定制解決方案與asych解決方案結合起來?

由於各種(可訪問性)原因,我將appSetting的內容保存在數據庫中,然后使用自定義緩存進行訪問。

自定義緩存的示例:

public enum ConfigurationSection
{
    AppSettings
}

public static class Utility
{
    #region "Common.Configuration.Configurations"

    private static Cache cache = System.Web.HttpRuntime.Cache;

    public static String GetAppSetting(String key)
    {
        return GetConfigurationValue(ConfigurationSection.AppSettings, key);
    }

    public static String GetConfigurationValue(ConfigurationSection section, String key)
    {
        Configurations config = null;

        if (!cache.TryGetItemFromCache<Configurations>(out config))
        {
            config = new Configurations();
            config.List(SNCLavalin.US.Common.Enumerations.ConfigurationSection.AppSettings);
            cache.AddToCache<Configurations>(config, DateTime.Now.AddMinutes(15));
        }

        var result = (from record in config
                      where record.Key == key
                      select record).FirstOrDefault();

        return (result == null) ? null : result.Value;
    }

    #endregion
}

namespace Common.Configuration
{
    public class Configurations : List<Configuration>
    {
        #region CONSTRUCTORS

        public Configurations() : base()
        {
            initialize();
        }
        public Configurations(int capacity) : base(capacity)
        {
            initialize();
        }
        public Configurations(IEnumerable<Configuration> collection) : base(collection)
        {
            initialize();
        }

        #endregion

        #region PROPERTIES & FIELDS

        private Crud _crud; // Db-Access layer

        #endregion

        #region EVENTS
        #endregion

        #region METHODS

        private void initialize()
        {
            _crud = new Crud(Utility.ConnectionName);
        }

        /// <summary>
        /// Lists one-to-many records.
        /// </summary>
        public Configurations List(ConfigurationSection section)
        {
            using (DbCommand dbCommand = _crud.Db.GetStoredProcCommand("spa_LIST_SecConfiguration"))
            {
                _crud.Db.AddInParameter(dbCommand, "@Section", DbType.String, section.ToString());

                _crud.List(dbCommand, PopulateFrom);
            }

            return this;
        }

        public void PopulateFrom(DataTable table)
        {
            this.Clear();

            foreach (DataRow row in table.Rows)
            {
                Configuration instance = new Configuration();
                instance.PopulateFrom(row);
                this.Add(instance);
            }
        }

        #endregion
    }

    public class Configuration
    {
        #region CONSTRUCTORS

        public Configuration()
        {
            initialize();
        }

        #endregion

        #region PROPERTIES & FIELDS

        private Crud _crud;

        public string Section { get; set; }
        public string Key { get; set; }
        public string Value { get; set; }

        #endregion

        #region EVENTS
        #endregion

        #region METHODS

        private void initialize()
        {
            _crud = new Crud(Utility.ConnectionName);
            Clear();
        }

        public void Clear()
        {
            this.Section = "";
            this.Key = "";
            this.Value = "";
        }
        public void PopulateFrom(DataRow row)
        {
            Clear();

            this.Section = row["Section"].ToString();
            this.Key = row["Key"].ToString();
            this.Value = row["Value"].ToString();
        }

        #endregion
    }
}

如果您的對象只是配置(加載一次,並且從那時開始一直保持只讀狀態),我將不必擔心它是單例還是是否/何時將被垃圾回收(除非將其設置為null,否則不會被回收) 。

通常,在服務器環境(如SharePoint)中,在考慮使對象成為單例之前,您需要確保有關該對象的兩件事:

  • 技術方面(主要是Prisoner ZERO指出的線程安全性,如果包含關鍵資源likle文件,還使用多少內存)
  • 安全方面-將用戶的信息泄漏到單例對象中並很容易被其他用戶誤用非常容易。 還可以將一個用戶可以訪問的單個信息緩存起來,然后由不應該訪問此類信息的另一用戶檢索。

我認為您可能過於復雜了,陷入了過早優化的陷阱。

您指出您的對象僅具有幾十個字符串/整數,因此大概您沒有進行任何昂貴的設置,因此采用單例方法實際上可以獲得任何好處嗎?

此外,這里真正的問題是這些字符串/整數將存儲在哪里-如果將其硬編碼到您的類中,那么您將無法輕松地對其進行更新,因此最好將該配置存儲在其他位置。

在SharePoint中存儲設置的六種方法

但是IHMO做到這一點的最佳方法是遵循MSDN SharePoint指導庫 ,該使用屬性包存儲來實現分層配置管理器,該管理器允許您執行諸如服務器場范圍設置之類的操作,但對於某些網站集/網站等卻被覆蓋。

所以總的來說,我個人會

  • 將配置對象實現為從配置管理器讀取值的簡單對象
  • Montor /個人資料,並在必要時更改為單身

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM