Если вы абсолютно хотите избежать 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()
для выполнения рекурсивных вызовов более глубоких объектов, если это необходимо.Следите за циклическими ссылками, если вы планируете это сделать. - Скрытые свойства все равно будут отображаться в выходном файле JSON, но свойства со значением всегда будут иметь значение
0
(ноль).) и свойства с типом ссылки всегда будут иметь значение null
.