我有一个巨大的XML文档,我必须解析它才能生成域对象。
因为文档很大,我不想在每次用户请求时解析它,而只是第一次,然后将所有对象保存到缓存中。
public List<Product> GetXMLProducts()
{
if (HttpRuntime.Cache.Get("ProductsXML") != null)
{
return (List<Product>)(HttpRuntime.Cache.Get("ProductsXML"));
}
string xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Content\\Products.xml");
XmlReader reader = XmlReader.Create(xmlPath);
XDocument doc = XDocument.Load(reader);
List<Product> productsList = new List<Product>();
// Parsing the products element
HttpRuntime.Cache.Insert("ProductsXML", productsList);
return productsList;
}
如何才能使这个功能在单例中运行并且是线程安全的最佳方法?
修复了将对象保存到缓存方法中的问题(复制粘贴错误)
答案 0 :(得分:10)
创建一个Lazy静态并在应用程序的生命周期内保留在内存中。并且不要忘记&#34; true&#34;部分原因在于它使线程安全。
public static readonly Lazy<List<Product>> _product = new Lazy<List<Products>>(() => GetProducts(), true);
要将其添加到模型中,只需将其设为私有并返回_product.Value;
public MyModel
{
... bunch of methods/properties
private static readonly Lazy<List<Product>> _products = new Lazy<List<Products>>(() => GetProducts(), true);
private static List<Product> GetProducts()
{
return DsLayer.GetProducts();
}
public List<Product> Products { get { return _products.Value; } }
}
要使用Lazy&lt;&gt;创建单身,请使用此模式。
public MyClass
{
private static readonly Lazy<MyClass> _myClass = new Lazy<MyClass>(() => new MyClass(), true);
private MyClass(){}
public static MyClass Instance { get { return _myClass.Value; } }
}
更新/编辑:
在上下文中使用的另一种懒惰模式(即会话)
会话中保存的某些模型:
public MyModel
{
private List<Product> _currentProducts = null;
public List<Product> CurrentProducts
{
get
{
return this._currentProducts ?? (_currentProducts = ProductDataLayer.GetProducts(this.CurrentCustomer));
}
}
}
答案 1 :(得分:2)
为了记录 - 一个懒惰的静态(克里斯盖斯勒的答案,从我得到+1)是一个很好的解决方案;在这种情况下,因为你总是想要内存中的数据。这个答案特别关注Cache
的使用(解决你的有些令人困惑的代码)并带来另一种初始化网站的方式。
执行此操作的传统方法是在Global.asax(.cs)中的Application_Start
处理程序中。不过,我将展示另一种不错的方式:
使用Nuget将WebActivator包添加到您的网站。
然后将以下代码添加到您在项目中创建的新文件夹中的新.cs文件中,名为App_Start
:
[assembly: WebActivator.PreApplicationStartMethod(typeof(*your_namespace*.MyInit),
"Start", Order = 0)]
namespace *your_namespace*
{
public static class MyInit {
public static void Start() {
string xmlPath = HostingEnvironment.MapPath("~/Content/Products.xml");
using(var reader = XmlReader.Create(xmlPath)) {
XDocument doc = XDocument.Load(reader);
List<Product> productsList = new List<Product>();
// Parsing the products element
HttpRuntime.Cache.Insert("ProductsXML", productsList);
}
}
}
}
注意 - 正确使用Cache.Insert,以及using
用于流阅读器。您的原始代码具有其他奇怪的逻辑和语义错误 - 例如尝试分配给函数的结果,如果它是null,则从缓存中返回值。
另请注意,您需要在上面的代码中添加一些名称空间 - 并注意*your_namespace*
。