/// <inheritdoc/> public IGetsFailureMessage GetNonGenericFailureMessageProvider(MessageProviderTypeInfo providerType, Type ruleInterface) { var ruleInterfaceInfo = ruleInterface.GetTypeInfo(); var method = getSingleGenericFailureMessageMethod.MakeGenericMethod(ruleInterfaceInfo.GenericTypeArguments[0]); return((IGetsFailureMessage)method.Invoke(this, new[] { providerType.ProviderType })); }
public void GetMessageProviderInfoShouldCreateProviderUsingLazyResolutionFromTheFactory([Frozen] IGetsCandidateMessageTypes typeRegistry, [Frozen] IGetsMessageProviderFactoryStrategy factoryStrategySelector, MessageProviderInfoFactory sut, int irrelevantPriority, [RuleResult] ValidationRuleResult ruleResult, IGetsNonGenericMessageProvider factory, IGetsFailureMessage provider) { MessageProviderTypeInfo type = new MessageProviderTypeInfo(typeof(string), irrelevantPriority); Mock.Get(typeRegistry).Setup(x => x.GetCandidateMessageProviderTypes(ruleResult)).Returns(new[] { type }); Mock.Get(factoryStrategySelector).Setup(x => x.GetMessageProviderFactory(type, ruleResult.RuleInterface)).Returns(factory); Mock.Get(factory).Setup(x => x.GetNonGenericFailureMessageProvider(type, ruleResult.RuleInterface)).Returns(provider); var result = sut.GetMessageProviderInfo(ruleResult); Assert.Multiple(() => { Mock.Get(factory).Verify(x => x.GetNonGenericFailureMessageProvider(type, It.IsAny <Type>()), Times.Never, "Because the provider hasn't been accessed, the factory should not have yet been used"); Assert.That(result.Single().MessageProvider, Is.SameAs(provider), "The returned message provider is the same as the expected one."); Mock.Get(factory).Verify(x => x.GetNonGenericFailureMessageProvider(type, ruleResult.RuleInterface), Times.Once, "Now that the provider has been accessed, the factory should have been executed"); }); }
public void GetCandidateMessageProviderTypesShouldAlwaysReturnWrappedResults([Frozen] IGetsCandidateMessageTypes wrapped, RuleWithMessageCandidateTypeDecorator sut, MessageProviderTypeInfo typeInfo1, MessageProviderTypeInfo typeInfo2, MessageProviderTypeInfo typeInfo3, [RuleResult] ValidationRuleResult result) { Mock.Get(wrapped).Setup(x => x.GetCandidateMessageProviderTypes(result)).Returns(new[] { typeInfo1, typeInfo2, typeInfo3 }); Assert.That(() => sut.GetCandidateMessageProviderTypes(result), Is.SupersetOf(new[] { typeInfo1, typeInfo2, typeInfo3 })); }
/// <summary> /// Initialises a new instance of <see cref="MessageProviderTypeInfo"/>. /// </summary> /// <param name="copyFrom">An instance to copy from.</param> /// <exception cref="ArgumentNullException">If <paramref name="copyFrom"/> is <see langword="null" />.</exception> protected MessageProviderTypeInfo(MessageProviderTypeInfo copyFrom) { if (copyFrom is null) { throw new ArgumentNullException(nameof(copyFrom)); } this.ProviderType = copyFrom.ProviderType; this.ProviderTypeInfo = copyFrom.ProviderTypeInfo; this.Priority = copyFrom.Priority; }
public void GetMessageProviderInfoShouldReturnProvidersCreatedFromRegistryTypeInfoExcludingThoseForWhichThereIsNoFactory([Frozen] IGetsCandidateMessageTypes typeRegistry, [Frozen] IGetsMessageProviderFactoryStrategy factoryStrategySelector, MessageProviderInfoFactory sut, int irrelevantPriority, [RuleResult] ValidationRuleResult ruleResult, IGetsNonGenericMessageProvider factory) { MessageProviderTypeInfo type1 = new MessageProviderTypeInfo(typeof(string), irrelevantPriority), type2 = new MessageProviderTypeInfo(typeof(int), irrelevantPriority), type3 = new MessageProviderTypeInfo(typeof(bool), irrelevantPriority); Mock.Get(typeRegistry).Setup(x => x.GetCandidateMessageProviderTypes(ruleResult)).Returns(new[] { type1, type2, type3 }); Mock.Get(factoryStrategySelector).Setup(x => x.GetMessageProviderFactory(type1, ruleResult.RuleInterface)).Returns(factory); Mock.Get(factoryStrategySelector).Setup(x => x.GetMessageProviderFactory(type2, ruleResult.RuleInterface)).Returns(() => null); Mock.Get(factoryStrategySelector).Setup(x => x.GetMessageProviderFactory(type3, ruleResult.RuleInterface)).Returns(factory); var result = sut.GetMessageProviderInfo(ruleResult); Assert.That(result.Select(x => x.ProviderType), Is.EquivalentTo(new[] { typeof(string), typeof(bool) })); }
/// <summary> /// Gets a message provider factory which is appropriate for the specified provider type and rule interface. /// </summary> /// <remarks> /// <para> /// This method will examine the message provider interfaces which are implemented by the /// <see cref="MessageProviderTypeInfo.ProviderTypeInfo"/> of the <paramref name="messageProviderTypeInfo"/>. /// Specifically it will consider all implementations of any of: /// </para> /// <list type="number"> /// <item><description><see cref="IGetsFailureMessage{TValidated, TParent}"/></description></item> /// <item><description><see cref="IGetsFailureMessage{TValidated}"/></description></item> /// <item><description><see cref="IGetsFailureMessage"/></description></item> /// </list> /// <para> /// It will then return a message-provider-factory strategy implementation which best-matches the interfaces /// indicated by the <paramref name="messageProviderTypeInfo"/>, based upon the actual validation rule interface /// which is in-use: <paramref name="ruleInterface"/>. /// </para> /// <para> /// This 'matching' process will look for matches in the order the message provider interfaces are listed /// above. For example, if a message provider implements the interface with two generic types, and for types that /// are compatible with the generic types present upon the rule interface, then the double-generic strategy /// will be given preference over a single-generic strategy. This is true even if the message provider type also /// implements a single-generic message provider interface that is compatible with the rule interface. /// </para> /// <para> /// Obviously, if the message provider type implements the non-generic <see cref="IGetsFailureMessage"/> then /// this will match every possible rule interface, as it is non-generic. This behaviour may be leveraged as /// a fall-back option for unexpected scenarios (such as validating <see cref="RuleOutcome.Errored"/> results). /// </para> /// <para> /// If this method cannot find any suitable strategy for getting a message provider - the provider type indicated /// by <paramref name="messageProviderTypeInfo"/> does not implement any interface which is compatible with the /// <paramref name="ruleInterface"/> - then it will return <see langword="null" />. This means that no factory /// strategy is applicable and that the provider type is not compatible with the rule interface. /// </para> /// </remarks> /// <param name="messageProviderTypeInfo">The candidate message provider type.</param> /// <param name="ruleInterface">The interface used for the validation rule.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">If any parameter is <see langword="null" />.</exception> public IGetsNonGenericMessageProvider GetMessageProviderFactory(MessageProviderTypeInfo messageProviderTypeInfo, Type ruleInterface) { if (messageProviderTypeInfo is null) { throw new ArgumentNullException(nameof(messageProviderTypeInfo)); } if (ruleInterface is null) { throw new ArgumentNullException(nameof(ruleInterface)); } if (messageProviderTypeInfo is InstanceMessageProviderInfo) { return(serviceProvider.GetRequiredService <UseExistingInstanceMessageProviderStrategy>()); } var providerTypeInfo = messageProviderTypeInfo.ProviderTypeInfo; var ruleInterfaceInfo = ruleInterface.GetTypeInfo(); if (!IsValidRuleInterface(ruleInterfaceInfo)) { throw GetIncorrectRuleInterfaceException(ruleInterface); } if (ImplementsDoubleGenericMessageInterface(providerTypeInfo, ruleInterfaceInfo)) { return(serviceProvider.GetRequiredService <DoubleGenericMessageProviderStrategy>()); } if (ImplementsSingleGenericMessageInterface(providerTypeInfo, ruleInterfaceInfo)) { return(serviceProvider.GetRequiredService <SingleGenericMessageProviderStrategy>()); } if (nonGenericProviderTypeInfo.IsAssignableFrom(providerTypeInfo)) { return(serviceProvider.GetRequiredService <NonGenericMessageProviderStrategy>()); } return(null); }
static MessageProviderTypeInfo GetNonGenericMessageProvider(ValidationRuleResult result, Type openGenericRuleInterface, Type openGenericRuleWithMessageInterface, Type openGenericAdapterType) { if (!result.RuleInterface.IsGenericType || result.RuleInterface.GetGenericTypeDefinition() != openGenericRuleInterface) { return(null); } var ruleWithMessageType = openGenericRuleWithMessageInterface.MakeGenericType(result.RuleInterface.GenericTypeArguments); if (!ruleWithMessageType.IsInstanceOfType(result.ValidationLogic.RuleObject)) { return(null); } var adapterType = openGenericAdapterType.MakeGenericType(result.RuleInterface.GenericTypeArguments); var provider = (IGetsFailureMessage)Activator.CreateInstance(adapterType, new[] { result.ValidationLogic.RuleObject }); var typeInfo = new MessageProviderTypeInfo(result.ValidationLogic.RuleObject.GetType(), priorityForRuleWithMessage); return(new InstanceMessageProviderInfo(typeInfo, provider)); }
/// <summary> /// Initialises a new instance of <see cref="LazyMessageProviderInfo"/>. /// </summary> /// <param name="typeInfo">Message provider type info.</param> /// <param name="messageProvider">A lazy message provider.</param> /// <exception cref="ArgumentNullException">If either <paramref name="typeInfo"/> or <paramref name="messageProvider"/> is <see langword="null" />.</exception> public LazyMessageProviderInfo(MessageProviderTypeInfo typeInfo, Lazy <IGetsFailureMessage> messageProvider) : base(typeInfo) { this.messageProvider = messageProvider ?? throw new ArgumentNullException(nameof(messageProvider)); }
/// <summary> /// Initialises a new instance of <see cref="MessageProviderInfo"/>. /// </summary> /// <param name="copyFrom">An instance to copy from.</param> /// <exception cref="ArgumentNullException">If <paramref name="copyFrom"/> is <see langword="null" />.</exception> protected MessageProviderInfo(MessageProviderTypeInfo copyFrom) : base(copyFrom) { }
/// <inheritdoc/> public IGetsFailureMessage GetNonGenericFailureMessageProvider(MessageProviderTypeInfo providerType, Type ruleInterface) => (IGetsFailureMessage)serviceProvider.GetService(providerType.ProviderType);
static Func <IGetsFailureMessage> GetProviderFactory(IGetsNonGenericMessageProvider factory, MessageProviderTypeInfo typeInfo, ValidationRuleResult ruleResult) { return(() => factory.GetNonGenericFailureMessageProvider(typeInfo, ruleResult.RuleInterface)); }
static MessageProviderInfo GetMessageProviderInfo(IGetsNonGenericMessageProvider factory, MessageProviderTypeInfo typeInfo, ValidationRuleResult ruleResult) => new LazyMessageProviderInfo(typeInfo, new Lazy <IGetsFailureMessage>(GetProviderFactory(factory, typeInfo, ruleResult)));
/// <inheritdoc/> public IGetsFailureMessage GetNonGenericFailureMessageProvider(MessageProviderTypeInfo providerType, Type ruleInterface) => ((InstanceMessageProviderInfo)providerType).MessageProvider;