简体   繁体   中英

Autofac is resolving IEnumerable<IContravariantInterface<ConcreteObject>> as IEnumerable<IContravariantInterface<object>>[0]

public interface IDomainValidator<in TDomain>{}

public interface IDomainValidation<TDomain> {
    void Validate(TDomain domain);
}

public class DomainValidation<TDomain> : IDomainValidation<TDomain>
{
    public DomainValidation(IEnumerable<IDomainValidator<TDomain>> validators)
    {
      ....
    }
}

I'm having an issue where contravariant interfaces are being resolved as an empty array of IEnumerable<IDomainValidator<object>> . My unit/integration tests are working fine so I have to assume there is something else being registered that is causing the problem.

Is there are way for me to determine how these Closed Types are being returned as object instead of the registered types that implement those closed types?

Update 1

I realized that I was calling this from a generic type and that it was actually the one that is likely to be having the problem. DomainValidation<TDomain> is also coming across with object which explains the list of domain validators. DomainValidation is being registered with:

builder.RegisterGeneric(typeof(DomainValidation<>)).As(typeof(IDomainValidation<>));

It is being injected into a class such as:

public class Implementation
{
    public Implementation(IDomainValidation<SomeClass> validation) {...}

}

This class is the one that technically is wrong. It is showing as object as well

Update 2

The IComponentRegistration is showing the correct type of IDomainValidation<SomeClass> , it does have the ContravariantAdapter and the service shows the correct type. the Target is showing up as + Target {Activator = DomainValidation 1 (ReflectionActivator), Services = [Flightdocs.Infrastructure.Validation.Domain.IDomainValidation 1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope} Autofac.Core.IComponentRegistration {Autofac.Core.Registration.ComponentRegistration} Which I'm guessing is where the problem is. Now I'm stuck as to why this is occurring. I'm assuming something is registering as IDomainValidation<object>

Since IContravariantInterface<T> is contravariant (eg it contains in arguments), it means that an IContravariantInterface<ConcreteObject> can be casted to IContravariantInterface<ConcreteSubObject> but not to IContravariantInterface<object> . Casting it to IContravariantInterface<object> would allow a consumer to pass in something completely different than ConcreteObject (eg System.String ) which would obviously break the class implementing IContravariantInterface<ConcreteObject> .

So from this sense it is obvious that a list of registered IContravariantInterface<ConcreteObject> would end up as zero instances of IContravariantInterface<object> . To be able to do this, you would have to change IContravariantInterface<T> to covarant (ie using the out keyword), but that would disable T as input argument.

I managed to figure out what my issue was. I have another module I use (MediatR) that suggested the use of builder.RegisterSource(new ContravariantRegistrationSource()); It apparently doesn't work so well with Contravariant generic interfaces. Once I removed it then those interfaces were filled with the correct object type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM