У меня есть метод, в котором я сравниваю свойства двух классов, которые используют один и тот же интерфейс. Существует несколько свойств, и вместо того, чтобы проверять их, я предпочел бы перебирать их, сохраняя повторяющееся кодирование. Я думал, что это возможно с отражением, но я не могу понять, как это сделать. Этот код не удался, поскольку я не понимал, что делаю.Сравнение свойств 2 объектов с одним и тем же интерфейсом
public void IsEqual(IPropertyComparer src, IPropertyComparer property)
{
PropertyInfo[] srcPI = src.GetType().GetPublicProperties();
PropertyInfo[] propertyPI = property.GetType().GetPublicProperties();
var numberOfProperties = srcPI.Count();
for (var i = 0; i < numberOfProperties; i++)
{
var srcValue = srcPI[i].GetValue(src, null);
var propertyValue = propertyPI[i].GetValue(property, null);
var propertyName = srcPI[i].Name;
if(srcValue.Equals(propertyValue) == false)
{
this.Action = "ValidateExistingPropertyFailOn" + propertyName;
this.Data.Error = true;
this.Data.ErrorMessage =
string.Format(this.Template, this.UPRN, propertyName, srcValue, propertyValue);
return;
}
}
В коде есть метод расширения. Метод расширения не работает, поскольку тип не распознается как интерфейс;
public static PropertyInfo[] GetPublicProperties(this Type type)
{
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
var subType = queue.Dequeue();
foreach (var subInterface in subType.GetInterfaces())
{
if (considered.Contains(subInterface))
{
continue;
}
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
var typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
var newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
}
return propertyInfos.ToArray();
}
return type.GetProperties(BindingFlags.FlattenHierarchy
| BindingFlags.Public | BindingFlags.Instance);
}
Как это «сбой»? Вы проследили его в отладчике, чтобы увидеть, где логика идет не так? У нас нет ваших ресурсов, чтобы иметь возможность воссоздать проблему. –
Сторона примечания - есть несколько способов, чтобы это могло пойти не так. Что, если типы имеют намеренно названные свойства, не связанные с интерфейсом, которые означают разные вещи? Я бы просто создал сопоставитель, который является _специфичным_ в этом интерфейсе, проверяет каждое свойство и не беспокоиться о «повторяющемся» коде. Если у вас слишком много свойств, чтобы сделать это, то ваш интерфейс делает слишком много, –
В дополнение к комментариям @ DStanley использование отражения (хотя оно работает, если выполнено правильно) значительно медленнее, чем прямое проверка свойств друг против друга. Делайте это только в коде, где вам не нужна производительность. – xxbbcc