我有一个在我的应用程序中使用的工作模型。我想通过公共API公开一些这些数据,但我有一些我不想返回一般消费的字段。一种费力的方法是创建一个单独的模型并创建使用automapper来映射我的输出以创建一些DTO系列。
我想做的是使用自定义属性注释我的模型,然后以某种方式使用某种扩展方法或web API actionfilter在将JSON发送到客户端之前在运行时过滤掉带注释的字段。我不能使用JsonIgnore,因为我需要这些字段用于我的应用程序中的操作。
有人可以给我一个如何做到这一点的概述吗?
提前致谢
编辑
所以我在想我可以使用newtonsoft的ShouldSerialize属性,但是我在找到一个优雅的方法设置一个触发它的条件时会感到茫然。我有一个复杂的模型,我想在运行时我需要反映整个输出,检测某个命名空间内的任何类,并设置一些值导致ShouldSerialize返回true
如果你绝对想要避免DTO和[JsonIgnore]
,并且真的想要使用自定义属性,你可能不得不使用一些反射。我将提出一个远非最佳选择的解决方案,但它可以为您提供一些想法。
首先,创建一个自定义属性来标记模型的属性,这些属性不应该通过公共API显示:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
class DontSendInPublicApiAttribute : Attribute { }
您必须创建一种方法来“擦除”您不想显示的对象属性上的数据。
public static void RemoveSecretData(object obj)
{
// Retrieve all public instance properties defined for the object's type and marked with [DontSendInPublicApi]
var propertiesToHide = obj.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetCustomAttribute<DontSendInPublicApiAttribute>() != null);
foreach (var prop in propertiesToHide)
{
// Set all of these properties in the given object to their default values.
// VALUE TYPES (ints, chars, doubles, etc.) will be set to default(TheTypeOfValue), by calling Activator.CreateInstance(TheTypeOfValue).
// REFERENCE TYPES will simply be set to null.
var propertyType = prop.PropertyType;
if (propertyType.IsValueType)
prop.SetValue(obj, Activator.CreateInstance(prop.PropertyType));
else
prop.SetValue(obj, null);
}
}
然后将该属性应用于模型中要隐藏的任何字段:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
[DontSendInPublicApi]
public string Occupation { get; set; }
[DontSendInPublicApi]
public int Salary { get; set; }
}
以下是如何调用它的示例:
var person = new Person() { Name = "John", Age = 29, Occupation = "Engineer", Salary = 200000 };
RemoveSecretData(person);
在RemoveSecretData(person)
执行之后,你将Occupation
对象的Salary
和person
属性设置为null
和0
,各自。
关于此解决方案的说明
RemoveSecretData()
方法以使用字段。[DontSendInPublicApi]
的属性的对象,则不会隐藏此属性。如有必要,您必须修改RemoveSecretData()
方法以对更深的对象执行递归调用。如果您打算这样做,请留意循环引用。0
(零),引用类型属性将始终显示值null
。