注册并解析通用对象

时间:2019-02-21 09:51:23

标签: automapper autofac

我在注册我的接口时遇到一些问题。 我有以下接口:

public interface IMapper<Q, T> { /* Mapper Helper Methods */ }
public interface ISourceObject { /* Properties */ }
public interface ITargetObject { /* Properties */ }

实现为:

public class GenericMapper<Q, T> : IMapper<Q,T> { /* Mapper Helper Methods */ }
public class SourceObject : ISourceObject { /* Properties */ }
public class TargetObject : ITargetObject { /* Properties */ }

在我的Autofac模块中,我想按以下方式注册它:

builder.RegisterType<GenericMapper<SourceObject, TargetObject>>().As<IMapper<ISourceObject, ITargetObject>>();

并通过以下方式解决该问题:

Container.Resolve<IMapper<ISourceObject, ITargetObject>>();

自动映射器配置文件配置为:

CreateMap<ISourceObject, ITargetObject>()
                    // ForMember Mappings
.ForAllMembers(o => o.Condition((src, dest, value) => value != null));

当我开始单元测试时,它崩溃并显示以下Stacktrace:

at Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, IEnumerable`1 services, IComponentRegistration target)
   at Autofac.Builder.RegistrationBuilder.CreateRegistration[TLimit,TActivatorData,TSingleRegistrationStyle](IRegistrationBuilder`3 builder)
   at Autofac.Builder.RegistrationBuilder.RegisterSingleComponent[TLimit,TActivatorData,TSingleRegistrationStyle](IComponentRegistry cr, IRegistrationBuilder`3 builder)
   at Autofac.RegistrationExtensions.<>c__DisplayClass3_0`1.<RegisterType>b__0(IComponentRegistry cr)
   at Autofac.ContainerBuilder.Build(IComponentRegistry componentRegistry, Boolean excludeDefaultModules)
   at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)

System.ArgumentException: 
    System.ArgumentException: The type 'App.Test.Models.GenericMapper`2[App.Test.Models.SourceObject,App.Test.Models.TargetObject]' is not assignable 
    to service 'App.Test.Models.IMapper`2[[App.Test.Models.ISourceObject, App.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],
    [App.Test.Models.ITargetObject, App.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'..

我在这里错了什么? 当我注册实施时,解决方案可以正常工作。但这将硬连线到实现中,我不希望这样。我可以这样解决吗,还是必须使用有线版本?

1 个答案:

答案 0 :(得分:0)

您所拥有的是接口定义的问题。如果您完全退出Autofac并手动对其进行测试,则可以看到证据:

[Fact]
public void TypesAreCompatible()
{
    var init = new GenericMapper<SourceObject, TargetObject>();
    var cast = (IMapper<ISourceObject, ITargetObject>)init;
    Assert.Same(init, cast);
}

这将在以var cast开头的行上失败并给出异常:

System.InvalidCastException : Unable to cast object of type 'GenericMapper`2[SourceObject,TargetObject]' to type 'IMapper`2[ISourceObject,ITargetObject]'.

原因是your IMapper interface is not covariant.用更简单的术语表示,您不能将更多派生的类型输入为Q或T并使其“神奇地起作用”。必须准确。

通过将out放在类型参数前面,更新您的界面,以告知C#使用协变类型是可以的。

public interface IMapper<out Q, out T> { }

一旦您这样做,我上面进行的测试将起作用... Autofac注册也将起作用。