简体   繁体   English

SharePoint Web部件和单例

[英]SharePoint Web Part & Singletons

I have a sharepoint project where we override search box and some other things. 我有一个共享项目,我们在其中覆盖搜索框和其他一些东西。 We also have a web part page that responds to the search box. 我们还有一个Web部件页面,可响应搜索框。 All these components should share single configuration. 所有这些组件应共享一个配置。 I thought about creating a singleton, but I am not sure how would that ever get cleaned up / removed from the memory / uninstalled. 我曾考虑过要创建一个单例,但不确定如何从内存中清除/删除/卸载。

Any ideas? 有任何想法吗? Any warnings about using singletons in sharepoint? 关于在共享点中使用单例的任何警告? Also, is there a proper way to share an instance of an object between all these componenets? 另外,是否存在在所有这些组件网络之间共享对象实例的适当方法?

Edit: I was thinking about a very simple singleton. 编辑:我正在考虑一个非常简单的单例。 Configuration only needs to contain 5-20 strings and a dozen integers at most. 配置最多只需要包含5-20个字符串和12个整数。 No complex objects :) 没有复杂的对象:)

As long as the objects being managed by your singleton class are thread-safe there shouldn't be an issue. 只要由您的singleton类管理的对象是线程安全的,就不会有问题。

EXAMPLE: 例:
I have a series of object-calls that were taking a long-time to process (7+ seconds). 我有一系列的对象调用需要很长时间才能处理(7+秒)。 So, I decided to try using a comet-styled long-polling technique to process them. 因此,我决定尝试使用彗星风格的长轮询技术来处理它们。 As such, I host a service (as a static singleton) in a single thread and process requests using asynchronous HttpHandler's...and it works GREAT! 这样,我在单个线程中托管了一个服务(作为静态单例),并使用异步HttpHandler来处理请求...并且效果很好! And because I'm using the service asynchronously it's highly efficient because the calling thread gets released immediately (upon completion of processing the service completes the callback). 而且由于我异步使用服务,所以它的效率很高,因为调用线程会立即释放(处理完服务后会完成回调)。

EDIT: 编辑:
But your problem of a long processing time still exists, so you still (probably) need an asynchronous solution for the initial fetch. 但是仍然存在处理时间长的问题,因此您(可能)仍需要异步解决方案来进行初始提取。 Hows this? 这个怎么样? Why not COMBINE the asych-solution with custom-caching? 为什么不将定制解决方案与asych解决方案结合起来?

For various (accessibility) reasons, I save my appSetting's in the database and use a custom-cache for access thereafter. 由于各种(可访问性)原因,我将appSetting的内容保存在数据库中,然后使用自定义缓存进行访问。

EXAMPLE of a Custom Cache: 自定义缓存的示例:

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

If your object is simply configuration (loaded once, and stays read only from that point) I'd not worry about it beeing singleton or about if/when it will be garbage collected (object will not be collected unless you set it to null). 如果您的对象只是配置(加载一次,并且从那时开始一直保持只读状态),我将不必担心它是单例还是是否/何时将被垃圾回收(除非将其设置为null,否则不会被回收) 。

In general in server environment (like SharePoint) you want to make sure 2 things about object before thinking about making it singleton: 通常,在服务器环境(如SharePoint)中,在考虑使对象成为单例之前,您需要确保有关该对象的两件事:

  • technical aspects (mainly thread safety as pointed by Prisoner ZERO, but also how much memory it uses, if it holds critical resources likle files) 技术方面(主要是Prisoner ZERO指出的线程安全性,如果包含关键资源likle文件,还使用多少内存)
  • security aspects - it is extremly easy to leak user's information into singleton object and use it by mistake by some other user. 安全方面-将用户的信息泄漏到单例对象中并很容易被其他用户误用非常容易。 It also possible to cache some information in singleton that one user have access to and than retrive by another user that should not have access to such information. 还可以将一个用户可以访问的单个信息缓存起来,然后由不应该访问此类信息的另一用户检索。

I think you may be over complicating this and falling into the trap of premature optimisation. 我认为您可能过于复杂了,陷入了过早优化的陷阱。

You indicate that your object doesn't have anything more than a couple of dozen strings/integers so presumably you're not doing any expensive setup and therefore is there actually anything to be gained going the singleton approach? 您指出您的对象仅具有几十个字符串/整数,因此大概您没有进行任何昂贵的设置,因此采用单例方法实际上可以获得任何好处吗?

Furthermore the real question here is where these strings/integers are going to be stored - if its hardcoded into your class then you can't update it easily so it would be better to store that config somewhere else. 此外,这里真正的问题是这些字符串/整数将存储在哪里-如果将其硬编码到您的类中,那么您将无法轻松地对其进行更新,因此最好将该配置存储在其他位置。

Six Ways to to store settings in SharePoint 在SharePoint中存储设置的六种方法

But IHMO the best way to do this is following the MSDN SharePoint Guidance Library which uses the Property Bag storage for their implementation of a hierarchical Configuration Manager which allows you to do things like a farm wide setting but overridden for certain site collections/sites etc. 但是IHMO做到这一点的最佳方法是遵循MSDN SharePoint指导库 ,该使用属性包存储来实现分层配置管理器,该管理器允许您执行诸如服务器场范围设置之类的操作,但对于某些网站集/网站等却被覆盖。

So in conclusion I personally would 所以总的来说,我个人会

  • Implement the config object as a simple object reading values from config manager 将配置对象实现为从配置管理器读取值的简单对象
  • Montor/profile and change to a singleton if necessary Montor /个人资料,并在必要时更改为单身

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

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