Этот ответ отредактирован
Ваш метод настроен на возврат одного Country
, но ваш код возвращает IEnumerable<Country>
.
Но проблема, похоже, решается по-разному в зависимости от версии .Net. Если вы используете .Net Core 2.2 (или позже в будущем), это должно работать:
public async Task<ActionResult<IEnumerable<Country>>> GetCountryRes()
{
var x = await ObjRepo.GetCountries();
return x;
}
Я искал фрагмент кода, который делал бы что-то подобное, помогающее при написании модульного теста. Вот что я в итоге использовал.
public static bool PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class
{
if (self != null && to != null)
{
Type type = typeof(T);
List<string> ignoreList = new List<string>(ignore);
foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
if (!ignoreList.Contains(pi.Name))
{
object selfValue = type.GetProperty(pi.Name).GetValue(self, null);
object toValue = type.GetProperty(pi.Name).GetValue(to, null);
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
{
return false;
}
}
}
return true;
}
return self == to;
}
РЕДАКТИРОВАТЬ:
Тот же код, что и выше, но с использованием методов LINQ и Extension:
public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class
{
if (self != null && to != null)
{
var type = typeof(T);
var ignoreList = new List<string>(ignore);
var unequalProperties =
from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
where !ignoreList.Contains(pi.Name) && pi.GetUnderlyingType().IsSimpleType() && pi.GetIndexParameters().Length == 0
let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
let toValue = type.GetProperty(pi.Name).GetValue(to, null)
where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))
select selfValue;
return !unequalProperties.Any();
}
return self == to;
}
public static class TypeExtensions
{
/// <summary>
/// Determine whether a type is simple (String, Decimal, DateTime, etc)
/// or complex (i.e. custom class with public properties and methods).
/// </summary>
/// <see cref="http://stackoverflow.com/questions/2442534/how-to-test-if-type-is-primitive"/>
public static bool IsSimpleType(
this Type type)
{
return
type.IsValueType ||
type.IsPrimitive ||
new[]
{
typeof(String),
typeof(Decimal),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(TimeSpan),
typeof(Guid)
}.Contains(type) ||
(Convert.GetTypeCode(type) != TypeCode.Object);
}
public static Type GetUnderlyingType(this MemberInfo member)
{
switch (member.MemberType)
{
case MemberTypes.Event:
return ((EventInfo)member).EventHandlerType;
case MemberTypes.Field:
return ((FieldInfo)member).FieldType;
case MemberTypes.Method:
return ((MethodInfo)member).ReturnType;
case MemberTypes.Property:
return ((PropertyInfo)member).PropertyType;
default:
throw new ArgumentException
(
"Input MemberInfo must be if type EventInfo, FieldInfo, MethodInfo, or PropertyInfo"
);
}
}
}
Удостоверьтесь, что объекты не null
.
Наличие obj1
и obj2
:
if(obj1 == null )
{
return false;
}
return obj1.Equals( obj2 );
Первая вещь, которую я предложил бы, будет состоять в том, чтобы разделить фактическое сравнение так, чтобы это было более читаемо (я также вынул ToString () - который необходим?):
else {
object originalProperty = sourceType.GetProperty(pi.Name).GetValue(this, null);
object comparisonProperty = destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null);
if (originalProperty != comparisonProperty)
return false;
следующее предложение состояло бы в том, чтобы минимизировать использование отражения как можно больше - это действительно медленно. Я имею в виду, действительно медленный. Если бы Вы собираетесь сделать это, я предложил бы кэшировать ссылки свойства. Я не глубоко знаком с API Reflection, поэтому если это немного выключено, просто корректируйтесь, чтобы заставить его скомпилировать:
// elsewhere
Dictionary<object, Property[]> lookupDictionary = new Dictionary<object, Property[]>;
Property[] objectProperties = null;
if (lookupDictionary.ContainsKey(sourceType)) {
objectProperties = lookupProperties[sourceType];
} else {
// build array of Property references
PropertyInfo[] sourcePropertyInfos = sourceType.GetProperties();
Property[] sourceProperties = new Property[sourcePropertyInfos.length];
for (int i=0; i < sourcePropertyInfos.length; i++) {
sourceProperties[i] = sourceType.GetProperty(pi.Name);
}
// add to cache
objectProperties = sourceProperties;
lookupDictionary[object] = sourceProperties;
}
// loop through and compare against the instances
Однако я должен сказать, что соглашаюсь с другими плакатами. Это пахнет ленивым и неэффективным. Необходимо реализовывать IComparable вместо этого :-).
Если Вы только сравниваете объекты того же типа или далее вниз цепочки наследования, почему бы не указать параметр как Ваш базовый тип, вместо того, чтобы возразить?
Также аннулируют, проверяет параметр также.
, Кроме того, я использовал бы 'var' только для создания кода более читаемым (если его c#3 кодируют)
кроме того, если объект имеет ссылочные типы как свойства затем, Вы просто называете ToString () на них, который действительно не сравнивает значения. Если ToString не является overwridden затем его просто попытка возвратить имя типа как строку, которая могла возвратить ложные положительные стороны.
Вы переопределяете.ToString () на всех Ваших объектах, которые находятся в свойствах? Иначе то второе сравнение могло возвратиться с пустым указателем.
кроме того, в том втором сравнении, я нахожусь на заборе о конструкции! (== B) по сравнению с (A! = B), с точки зрения удобочитаемости годы шести месяцев/двух с этого времени. Сама строка довольно широка, который в порядке, если Вы имеете широкий монитор, но не могли бы распечатать очень хорошо. (придеритесь к мелочам)
, все Ваши объекты всегда с помощью свойств, таким образом, что этот код будет работать? Могли быть некоторые внутренние, неимущие данные, которые могли отличаться от одного объекта до другого, но все выставленные данные являются тем же? Я думаю о некоторых данных, которые могли изменяться со временем, как два генератора случайных чисел, которые, оказывается, поражают то же число однажды, но собираются произвести две различных последовательности информации или просто любые данные, которые не становятся выставленными через интерфейс свойства.
Я думаю, что было бы лучше следовать за шаблоном для Переопределения Object#Equals ()
Для лучшего описания: Read Bill Wagner Эффективный C# - Объект 9 я думаю
public override Equals(object obOther)
{
if (null == obOther)
return false;
if (object.ReferenceEquals(this, obOther)
return true;
if (this.GetType() != obOther.GetType())
return false;
# private method to compare members.
return CompareMembers(this, obOther as ThisClass);
}
декабрь обновления 2011: