如何利用Expression Tree递归加密类/接口的String及嵌套属性?
问题描述
我已经掌握Expression Tree的基础知识,但在实现以下功能时遇到阻碍:需要修改类/接口实例,找出所有string属性并加密,同时递归处理所有“子”类/接口属性,包括IEnumerable<T>(其中T : class)。加密逻辑已经完成,但用Expression Tree实现对任意传入T的通用处理超出了当前理解范围。之前用反射实现过,但性能很快出现问题,以下是目前完成的代码:
使用AggregateHelper和PropertyHelper类,已实现基础的string加密:
测试类
public class SimpleEncryptionTest { public string String1 { get; set; } } public class NestedClassEncryptionTest { public string SomeString { get; set; } public SimpleEncryptionTest Inner { get; set; } } public class ListClassEncryptionTest { public List<string> StringList { get; set; } }
单元测试
[TestMethod] public void Encryption_works_on_a_simple_class() { var testString = "this is only a test. If this had been a real emergency..."; var sut = new SimpleEncryptionTest() { String1 = testString }; sut.EncryptStringProperties(); Assert.AreNotEqual(testString, sut.String1); } [TestMethod] public void Round_trip_works_on_a_simple_class() { var testString = "what string should I use?"; var sut = new SimpleEncryptionTest() { String1 = testString }; sut.EncryptStringProperties(); sut.DecryptStringProperties(); Assert.AreEqual(testString, sut.String1); } [TestMethod] public void Round_trip_works_in_nested_class_scenario() { var outerString = "what is your name?"; var innerString = "Tony; what's your name?"; var sut = new NestedClassEncryptionTest{ SomeString = outerString, Inner = new SimpleEncryptionTest(){String1 = innerString } }; sut.EncryptStringProperties(); Assert.AreNotEqual(outerString, sut.SomeString); Assert.AreNotEqual(innerString, sut.Inner.String1); sut.DecryptStringProperties(); Assert.AreEqual(outerString, sut.SomeString); Assert.AreEqual(innerString, sut.Inner.String1); } [TestMethod] public void Round_trip_works_on_lists() { var testone = "one"; var testtwo = "two"; var testStrings = new List<string>() { testone, testtwo }; var sut = new ListClassEncryptionTest() { StringList = testStrings }; sut.EncryptStringProperties(); Assert.AreNotEqual(testone, sut.StringList[0]); Assert.AreNotEqual(testtwo, sut.StringList[1]); sut.DecryptStringProperties(); Assert.AreEqual(testone, sut.StringList[0]); Assert.AreEqual(testtwo, sut.StringList[1]); }
加密/解密扩展方法
/// <summary> /// Iterates through an Object's properties and encrypts any strings it finds, /// recursively iterating any class or interface Properties. /// </summary> /// <typeparam name="T">Any type</typeparam> /// <param name="genericObj">The object to encrypt</param> /// <returns>The original object, with its string values encrypted.</returns> public static T EncryptStringProperties<T>(this T obj) where T : class { return Crypt(obj, EncryptStringAction); } /// <summary> /// Iterates through an Object's properties and decrypts any strings it finds, /// recursively iterating any class or interface Properties. /// </summary> /// <typeparam name="T">Any type</typeparam> /// <param name="genericObj">The object to decrypt</param> /// <returns>The original object, with its string values decrypted.</returns> public static T DecryptStringProperties<T>(this T obj) { return Crypt(obj, DecryptStringAction); } private static T Crypt<T>(T obj, Action<PropertyHelper<T, string>, T> action) { var stringProperties = new AggregateHelper<T, string>(); foreach (var property in stringProperties.Properties) { var propertyHelper = stringProperties[property]; action(propertyHelper, obj); } // how do I find the nested classes, interfaces and lists // using Expression Trees to feed them through the same processing? return obj; } private static void EncryptStringAction<T>(PropertyHelper<T, string> prop, T genericObj) { var plainTextValue = (string)prop.GetValue(genericObj); prop.SetValue(genericObj, plainTextValue.ToEncryptedString()); } private static void DecryptStringAction<T>(PropertyHelper<T, string> prop, T genericObj) { var encryptedValue = (string)prop.GetValue(genericObj); prop.SetValue(genericObj, encryptedValue.ToDecryptedString()); }
目前代码可加密任意object的string属性,但无法递归处理嵌套对象、接口及集合,需要实现用Expression Tree找到嵌套类/接口属性并传入EncryptStringProperties方法,同时处理包含string的IEnumerable。
内容的提问来源于stack exchange,提问作者Scott Baker
相关产品推荐
相关产品推荐

