К memoizing его результат. Сохраните результат в Dictionary<Type, PropertyInfo[]>
, затем в начале функции проверьте, вы уже рассчитали его. Если да, верните значение Dictionary<,>
. Если вы хотите сделать его потокобезопасным, используйте ConcurrentDictionary<Type, PropertyInfo[]>
.
Что-то вроде:
//private static readonly Dictionary<Type, PropertyInfo[]> PasswordProperties = new Dictionary<Type, PropertyInfo[]>();
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PasswordProperties = new ConcurrentDictionary<Type, PropertyInfo[]>();
public static object GetObjectToSerialize(object value, Type targetType) {
Type type = value.GetType();
PropertyInfo[] properties;
if (!PasswordProperties.TryGetValue(type, out properties))
{
properties = type.GetProperties()
.Where(p => p.PropertyType == typeof(string))
.Where(p => p.Name.Contains("Password"))
.ToArray();
var passwordWithoutEncryptedAttribute = properties
.Where(p => !p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());
if (passwordWithoutEncryptedAttribute.Any()) {
throw new InvalidOperationException(); // SafeFormatter.Format(BackgroundJobsLocalization.Culture, BackgroundJobsLocalization.PasswordWithoutEncryptedAttribute));
}
PasswordProperties[type] = properties;
}
foreach (var property in properties)
{
property.SetValue(value, null, null);
}
return value;
}
Если у вас есть доступ к типу value
во время компиляции, это оптимизируемое по-другому, по memoizing внутри поля статического универсального класса:
public static class ObjectHelper
{
public static T GetObjectToSerialize<T>(T value)
{
foreach (var property in ObjectHelperInner<T>.Properties)
{
property.SetValue(value, null, null);
}
return value;
}
private static class ObjectHelperInner<T>
{
public static readonly PropertyInfo[] Properties;
static ObjectHelperInner()
{
PropertyInfo[] properties = typeof(T).GetProperties()
.Where(p => p.PropertyType == typeof(string))
.Where(p => p.Name.Contains("Password"))
.ToArray();
var passwordWithoutEncryptedAttribute = properties
.Where(p => !p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());
if (passwordWithoutEncryptedAttribute.Any()) {
throw new InvalidOperationException(); // SafeFormatter.Format(BackgroundJobsLocalization.Culture, BackgroundJobsLocalization.PasswordWithoutEncryptedAttribute));
}
Properties = properties;
}
}
}
Это вторая версия кода не работать, если у вас есть:
object obj = something;
ObjectHelper.GetObjectToSerialize(obj);
Это будет работать только если у вас есть:
SomeConcreteType obj = something;
ObjectHelper.GetObjectToSerialize(obj);
Другим возможным решением является создание (через Expression
деревьев) код во время выполнения, чтобы очистить объект. Он становится намного быстрее, но генерация кода становится намного медленнее. И код для этого гораздо сложнее.
Почему вы не добавляете атрибуты сериализатора? –
Зачем его добавлять? –
Вы знаете, что вы устанавливаете значение 'null' значения' Password' в 'foreach', правильно? – xanatos