DictionaryContainsKeyConstraint
DictionaryContainsKeyConstraint is used to test whether a dictionary
contains an expected object as a key.
using NUnit.Framework.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NUnit.Framework.Constraints
{
[NullableContext(1)]
[Nullable(0)]
public class DictionaryContainsKeyConstraint : CollectionItemsEqualConstraint
{
private const string ContainsMethodName = "Contains";
private readonly bool _isDeprecatedMode;
public override string DisplayName => "ContainsKey";
public override string Description => "dictionary containing key " + MsgUtils.FormatValue(Expected);
protected object Expected { get; }
public DictionaryContainsKeyConstraint(object expected)
: base(expected)
{
Expected = expected;
}
public DictionaryContainsKeyValuePairConstraint WithValue([Nullable(2)] object expectedValue)
{
return base.Instead.Append(new DictionaryContainsKeyValuePairConstraint(Expected, expectedValue));
}
[NullableContext(2)]
private bool Matches(object actual)
{
if (actual == null)
throw new ArgumentException("Expected: IDictionary But was: null", "actual");
if (_isDeprecatedMode) {
IDictionary dictionary = ConstraintUtils.RequireActual<IDictionary>(actual, "actual", false);
foreach (object key in dictionary.Keys) {
if (ItemsEqual(key, Expected))
return true;
}
return false;
}
MethodInfo containsKeyMethod = GetContainsKeyMethod(actual);
if ((object)containsKeyMethod != null)
return (bool)containsKeyMethod.Invoke(actual, new object[1] {
Expected
});
throw new ArgumentException("The " + TypeHelper.GetDisplayName(actual.GetType()) + " value must have a ContainsKey or Contains(TKey) method.");
}
public override ConstraintResult ApplyTo<[Nullable(2)] TActual>(TActual actual)
{
return new ConstraintResult(this, actual, Matches(actual));
}
protected override bool Matches(IEnumerable collection)
{
return Matches(collection);
}
[return: Nullable(2)]
private static MethodInfo GetContainsKeyMethod(object keyedItemContainer)
{
Type type = keyedItemContainer.GetType();
return FindContainsKeyMethod(type) ?? type.GetInterfaces().Concat(GetBaseTypes(type)).Select(FindContainsKeyMethod)
.FirstOrDefault((MethodInfo m) => (object)m != null);
}
[return: Nullable(2)]
private static MethodInfo FindContainsKeyMethod(Type type)
{
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
MethodInfo method = methods.FirstOrDefault(delegate(MethodInfo m) {
if (m.ReturnType == typeof(bool) && (m.Name == "ContainsKey" || (m.Name == "Contains" && m.DeclaringType == typeof(IDictionary))) && !m.IsGenericMethod)
return m.GetParameters().Length == 1;
return false;
});
if ((object)method == null && type.IsGenericType) {
Type genericTypeDefinition = type.GetGenericTypeDefinition();
Type tKeyGenericArg = genericTypeDefinition.GetGenericArguments().FirstOrDefault((Type typeArg) => typeArg.Name == "TKey");
if ((object)tKeyGenericArg != null) {
method = genericTypeDefinition.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) {
if (m.ReturnType == typeof(bool) && m.Name == "Contains" && !m.IsGenericMethod && m.GetParameters().Length == 1)
return m.GetParameters()[0].ParameterType == tKeyGenericArg;
return false;
});
if ((object)method != null)
method = methods.Single((MethodInfo m) => m.MetadataToken == method.MetadataToken);
}
}
return method;
}
private static IEnumerable<Type> GetBaseTypes(Type type)
{
Type baseType = type.BaseType;
while ((object)baseType != null) {
yield return baseType;
baseType = baseType.BaseType;
}
}
}
}