C# 如何在ASP.Net会话中仅存储对象的一部分?
我处理一些可以引用大型DataTable的对象。我希望将这些对象存储在会话中,而不使用数据表,因为这些对象可以很容易地重新生成,并且我希望节省一些内存 有没有一种有效的方法可以做到这一点 我试过的东西:C# 如何在ASP.Net会话中仅存储对象的一部分?,c#,asp.net,session,memory,C#,Asp.net,Session,Memory,我处理一些可以引用大型DataTable的对象。我希望将这些对象存储在会话中,而不使用数据表,因为这些对象可以很容易地重新生成,并且我希望节省一些内存 有没有一种有效的方法可以做到这一点 我试过的东西: 想想看 避免在想到第一个工作时感觉很好,因为可能存在更好的方法 承认我的知识有限 询问堆栈溢出 希望有一个有趣的发现 您可以像下面这样创建接口,并将其应用于需要此行为的类 public interface IClearBeforeSessionStore { public void Cle
- 想想看
- 避免在想到第一个工作时感觉很好,因为可能存在更好的方法
- 承认我的知识有限
- 询问堆栈溢出
- 希望有一个有趣的发现
public interface IClearBeforeSessionStore
{
public void ClearWhichAreBigger();
}
public class A : IClearBeforeSessionStore
{
public DataTable dt {get;set;}
public string AnyString { get;set;}
public void ClearWhichAreBigger()
{
this.dt = null;
}
}
像这样在会话中存储类对象
A objA = new A();
objA.AnyString = "Object A";
objA.dt = new DataTable(); // or any existing one
Session["objA"] = objA.ClearWhichAreBigger();
当您像下面这样从会话中获取它时,您只能访问AnyString属性
A objA = Session["objA"] as A;
if(objA.AnyString == "Object A" && objA.dt == null)
{
// yes I am from session !!!!
}
您可以向类中添加一个“复制构造函数”,该类将复制除您不需要的成员之外的所有成员,如下所示:
public class BigData
{
private string _someValue;
private DataSet _bigDataSet;
public BigData()
{
...
}
public BigData(BigData toBeCloned)
{
this._someValue = toBeCloed._someValue;
// Don't copy _bigDataSet here!
}
}
session["BigDataWithoutDataSet"] = new BigData(bigDataContainingDataSet);
然后,您可以向会话添加如下内容:
public class BigData
{
private string _someValue;
private DataSet _bigDataSet;
public BigData()
{
...
}
public BigData(BigData toBeCloned)
{
this._someValue = toBeCloed._someValue;
// Don't copy _bigDataSet here!
}
}
session["BigDataWithoutDataSet"] = new BigData(bigDataContainingDataSet);
您可以使用通用解决方案来取消用自定义属性修饰的类的属性。例如,可以创建以下属性和类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace MvcApp
{
[AttributeUsage(AttributeTargets.Property)]
public class NullifyAttribute : Attribute
{
}
public class PropertyNullifier
{
public static T Nullify<T>(T original)
where T : class
{
// Limitations:
// 1) only works for POCOs with public properties: t.GetProperties()
// 2) only works for classes with public constructor
// 3) it's not recursive
Type t = original.GetType();
// This looks for all the properties that are not marked with nullified
List<PropertyInfo> notNullifiedProperties =
t.GetProperties() // 1)
.Where(p => !p.GetCustomAttributes(typeof (NullifyAttribute), true).Any())
.ToList();
// This creates an instance of the object
T copy = Activator.CreateInstance<T>(); // 2)
// And this copy the non-nullified properties
foreach (var p in notNullifiedProperties)
{
p.SetValue(copy, p.GetValue(original)); // 3) apply recursion to 2nd parameter
}
return copy;
}
}
}
但是,使用此解决方案,在会话中存储之前,您仍然必须使用空值发生器。
另一个选项是创建自己的用于存储会话的类,并更改web.config以使用它。这样,您可以在存储之前自动清空
这不是一个非常普遍的解决办法。因此,您可以做一些更复杂的事情:创建自己的自定义会话状态存储,并配置web.confgi以使用它。这里有一个完整的工作示例:。您必须修改此示例以使用nullifier类,或者使用它修改序列化方法以忽略自定义属性修饰属性,检查它们是否修饰(使用代码中相应的部分)
采取额外的工作,使其或多或少自动化,并确定这是否有效,取决于您的项目的细节
想让它更简单吗?好吧,你够幸运的了。如果更改,它将自动使用序列化。然后你就可以使用。但这可能是危险的:如果您试图存储不可序列化的对象,您将得到一个异常
正如您所见,没有最佳解决方案:只选择最适合您的解决方案。您可以为数据表特定的属性或该对象的变量指定空值。何时执行此操作以确保当前进程仍然没有使用数据表?或者创建一个新类,该类包含您需要的所有这些值的属性如何关心并拥有一个接受现有对象类型的构造函数,并将该新类实例存储在会话中?是否要为所有数据表自动执行此操作?您是否要明确地针对特定情况执行此操作?是否要使用自定义属性装饰不应序列化的属性?你尝试了什么,失败了什么?如果某个属性有魔力,请告诉我。