如何使控制器对象在会话之间存活?
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
本身不是单例(它确实委托给一个单例,因为缓存的要点是它可以集中访问,但这被隐藏为实现细节。其他实现将以不同的方式访问缓存,但接口是相同的,您的应用程序将不会意识到更改。)
我需要我的控制器在会话之间存储数据。因此,如果数据在会话期间保存在对象中的列表中,则在下一个会话开始时数据仍会存在。此外,我需要所有客户端共享同一个控制器及其保存的数据,即单例。
除了使它的所有成员 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
本身不是单例(它确实委托给一个单例,因为缓存的要点是它可以集中访问,但这被隐藏为实现细节。其他实现将以不同的方式访问缓存,但接口是相同的,您的应用程序将不会意识到更改。)