如何使控制器对象在会话之间存活?

How can I make the controller object survive between sessions?

我需要我的控制器在会话之间存储数据。因此,如果数据在会话期间保存在对象中的列表中,则在下一个会话开始时数据仍会存在。此外,我需要所有客户端共享同一个控制器及其保存的数据,即单例。

除了使它的所有成员 static 是一个糟糕的解决方案之外,我该如何实现?

您可以使用 HttpRuntime.Cache 或 Singleton。

all clients to share the same controller and the data it holds

HttpRuntime.Cache 是该场景的不错选择。

请注意,当 AppDomain 回收或应用程序崩溃时,缓存将被清除。

已更新:

Cache和Singleton在Memory中存储数据基本相同。

但是,Cache 具有额外的功能 - 例如 Web Farm 和 Web Garden 中的过期和分布式缓存。

public class Singleton
{
    static Singleton()
    {
        allSingletons = new Dictionary<Type, object>();
    }

    static readonly IDictionary<Type, object> allSingletons;

    public static IDictionary<Type, object> AllSingletons
    {
        get { return allSingletons; }
    }
}

public class Singleton<T> : Singleton
{
    static T instance;

    public static T Instance
    {
        get { return instance; }
        set
        {
            instance = value;
            AllSingletons[typeof(T)] = value;
        }
    }
}

// Usage 
Singleton<IList<string>>.Instance = new List<string> { "One", "Two", "Three" };
IList<string> collection = Singleton<IList<string>>.Instance;

如果您有一个数据列表应该可供跨会话的多个请求使用,请使用某种中央存储库来存储它。这可以是数据库或缓存,甚至是单例对象。如果对象是一个 运行-time 对象(也就是说,你将它存储在缓存中,而不是数据库中),不要直接使用单例或 HttpRuntime.Cache - 实现某种 ICache 接口并在您的其余代码中使用它,因此您没有在代码中到处硬编码的特定实现。

例如:

public interface ICache
{
    void Add ( string cacheKey, object itemToAdd, TimeSpan itemLifeTime );
    object Get ( string cacheKey );
    object Remove ( string cacheKey );
}

这是一个非常简单的界面,仅供示例;在生产代码中,您希望通过更好的类型支持、更多选项等对其进行更精细的调整。但是,它必须足够简单,以便您可以轻松地交换其背后可能不兼容的实现。

有了这个之后,您可以根据需要创建多个缓存实现,并在 运行 时加载您想要的一个。例如,一个特定的实现可以使用 Cache,只要数据仅在单个服务器上需要(Cache 是本地的,因此服务器场中的多个服务器不共享相同的缓存) .

public class LocalCache : ICache
{
    public void Add ( string cacheKey, object itemToAdd, TimeSpan itemLifeTime )
    {
        HttpRuntime.Cache.Add ( ... );
    }

    public object Get ( string cacheKey )
    {
        return ( HttpRuntime.Cache.Get  ( ... ) );
    }

    public object Remove ( string cacheKey )
    {
        return ( HttpRuntime.Cache.Remove ( ... ) );
    }
}

这将为您提供本地缓存的实现。如果以后需要分布式缓存,您可以轻松地创建一个与分布式缓存对话的新实现(Couchbase 是一种可能性,但还有其他可能性)。

实现后,您可以使用 IoC 库(如 LightInject 或其他)来实例化您想要的特定实现,这样您就可以避免在代码中对特定类型进行硬编码。

如您所见,LocalCache 本身不是单例(它确实委托给一个单例,因为缓存的要点是它可以集中访问,但这被隐藏为实现细节。其他实现将以不同的方式访问缓存,但接口是相同的,您的应用程序将不会意识到更改。)