您可以使用通用解决方案来取消使用自定义属性修饰的类的属性。例如,您可以创建此属性和类:
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;
}
}
}
注意 cmets 的限制!!至少,这不会修改原始对象,而是进行浅拷贝(将引用复制到引用属性),速度非常快。额外的限制是速度。这可以通过多种方式进行改进,例如缓存未无效的属性,使用反射而不是激活器,将其修改为仅在存在可无效属性时创建副本。最后一个改进很容易实现。添加此代码:if (notNullifiedProperties.Count == 0) return original;
然后,在将对象存储到 Session 之前,将其属性无效并存储此对象的无效副本。此单元测试解释了如何使无效(您将无效对象存储在会话中)。
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcApp;
namespace Test.MvcApp
{
public class SampleClass
{
[Nullify]
public string Name { get; set; }
public int Age { get; set; }
}
[TestClass]
public class PropertyNullifierTest
{
[TestMethod]
public void TestMethod1()
{
SampleClass sampleObject = new SampleClass
{
Name = "John Smith",
Age = 22,
};
SampleClass nullified = PropertyNullifier.Nullify(sampleObject);
Assert.IsNull(nullified.Name);
Assert.AreEqual(sampleObject.Age, nullified.Age);
}
}
}
但是,使用此解决方案,您仍然必须在存储到会话之前使用 nullifier。
另一种选择是创建自己的类来存储会话,并更改 web.config 以使用它。这样就可以在存储前自动作废。
这不是一个非常通用的解决方案。所以你可以做一些更复杂的事情:创建你自己的自定义会话状态存储,并配置 web.confgi 以使用它。这里有一个完整的工作示例:of this solution。您必须修改此示例以使用 nullifier 类或使用它修改序列化方法以忽略自定义属性修饰属性,检查它们是否被修饰(使用我的代码的对应部分)。
采取额外的工作使其或多或少自动化,并确定这是否有效,取决于您的项目细节。
想要更轻松吗?好吧,你很幸运。如果更改Session mode to State Server,它将自动使用序列化。然后您可以使用standard NonSerialized attribute。但这可能很危险:如果你尝试存储不可序列化的对象,你会得到一个异常。
正如您所见,没有最佳解决方案:只选择最适合您的解决方案。