/// <summary> /// Validates that the information provided around the type discoverer /// is valid. For example, ensures that the provided type information /// refers to an <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer" /> that can be constructed. /// Or, in other words, that the following conditions are met: /// <list type="bullet"> /// <item>The type discoverer type information is not null.</item> /// <item>Type discoverer type implements the <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer"/> /// interface.</item> /// <item>Type has a public no-args constructor or a constructor which /// matches the provided argument type information.</item> /// </list> /// </summary> /// <param name="info"> /// The details surrounding the /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="info"/> has a <see /// cref="TypeDiscovererInfo.DiscovererType" /> that is null. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when <paramref name="info"/> has a <see /// cref="TypeDiscovererInfo.DiscovererType" /> does not /// implement <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when <paramref name="info"/> has a <see /// cref="TypeDiscovererInfo.DiscovererType" /> that does not /// have a constructor which matches the provided <see /// cref="TypeDiscovererInfo.DiscovererArgumentTypes" /> /// </exception> public static void AssertIsValidDiscovererType(TypeDiscovererInfo info) { if (info is null) { throw new ArgumentNullException(nameof(info), $"{nameof(info)} must be non-null."); } AssertIsNotNull(info.DiscovererType); AssertImplementsProperInterface(info.DiscovererType); AssertHasArgumentsThatMatchConstructorArguments(info); }
/// <summary> /// Creates an instance of the attribute specifying that the /// <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer"/> should be of type /// <paramref name="typeDiscovererType"/>. /// </summary> /// <param name="typeDiscovererType"> /// The type of the <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer"/> to be used. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="typeDiscovererType"/> is null. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when <paramref name="typeDiscovererType"/> does not /// implement <see cref="NUnit.Extension.DependencyInjection.Abstractions.ITypeDiscoverer"/>. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Thrown when <paramref name="typeDiscovererType"/> does not /// have a public no-args constructor. /// </exception> public NUnitTypeDiscovererAttribute(Type typeDiscovererType) { TypeDiscovererInfo = new TypeDiscovererInfo { DiscovererType = typeDiscovererType, DiscovererArgumentTypes = new Type[] {}, DiscovererArguments = new object[] {} }; TypeDiscovererTypeValidator.AssertIsValidDiscovererType(TypeDiscovererInfo); }
private static void AssertHasArgumentsThatMatchConstructorArguments(TypeDiscovererInfo info) { var discovererType = info.DiscovererType; var argumentTypes = info.DiscovererArgumentTypes; var argumentTypeNames = argumentTypes.Select(x => x.FullName); var ctorInfo = info.DiscovererType.GetConstructor( BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Standard, argumentTypes, null); if (ctorInfo == null) { throw new ArgumentOutOfRangeException( nameof(info), $"{discovererType.FullName} specified as {nameof(ITypeDiscoverer)} on " + $"{nameof(NUnitTypeDiscovererAttribute)} must have a constructor which corresponds " + $"to the argument types which were provided: {string.Join(", ", argumentTypeNames)}." ); } }