示例输入:
// remove sensitive data
var user = db.Users.Where(x => x.Id == '123').ToList()
.Omit("PasswordHash", "PasswordSalt", "SecretDataAsInteger");
输出:
{
FirstName: "...",
LastName: "...",
PasswordHash: "", // default value instead of real value
PasswordSalt: "",
SeretDataAsInteger: 0
}
类似于: https://lodash.com/docs/4.16.4#omit
设定:
var user = ..Users.Select(x => new User {/* here I set each property */})
因为这会导致更新所有引用,以防我稍后更新了User
模型属性
答案 0 :(得分:1)
下面是我为您创建的一个类,应该使用提供的属性名称列表将它们设置为Property类型的默认值。使用您的示例:
// remove sensitive data
var user = db.Users.Where(x => x.Id == '123').ToList()
.OmitProperties("PasswordHash", "PasswordSalt", "SecretDataAsInteger");
请记住加入System.Reflection
。
public static class EnumerableExtensions {
public static IEnumerable<T> OmitProperties<T>(this IEnumerable<T> enumerable, params string[] propertyNames) {
PropertyInfo[] propertiesToOmit = typeof(T).GetProperties()
.Where(p => propertyNames.Contains(p.Name))
.ToArray();
foreach (var item in enumerable) {
foreach (var property in propertiesToOmit) {
property.SetValue(item, null);
}
yield return item;
}
}
}
答案 1 :(得分:1)
如果您可以控制User
类,则可以添加User
的构造函数。使此构造函数复制所有字段。您可以使用反射来轻松地这样做。如果通过动态生成执行所需工作的辅助方法来实现此功能,则只需生成一次辅助方法。给定此构造函数,您可以编写
var user = db.Users.Where(x => x.Id == 123).AsEnumerable()
.Select(x => new User(x) {
PasswordHash = "",
PasswordSalt = "",
SecretDataAsInteger = 0
}).ToList();
这使其保持类型安全:您不会意外省略User
没有的属性(例如,您尝试省略PasswordSlat
而不是PasswordSalt
),并且您不能通过将属性设置为属性类型不支持的值(例如,通过将其设置为SecretDataAsInteger
来尝试省略null
)来意外省略属性,并且无论如何都会尝试这样做由编译器标记而不是在运行时爆炸。
答案 2 :(得分:1)
这是一个不是Linq并实际更新基础对象的选项。可能不是你想要的,但它完成了这项工作:
public static IEnumerable<T> ApplyToAll<T>(this IEnumerable<T> sequence,
params Action<T>[] action)
{
foreach (var element in sequence)
{
foreach (var action in actions)
{
omission(action);
}
yield return element;
}
}
而不是传递属性的字符串名称,而是传递一些作用于输入的操作:
var redactedUsers = users.ApplyToAll(
u => u.Password = "",
u => u.Name = "Hello " + u.Name);