简体   繁体   English

Autofac 注册具有具体类型的泛型实例

[英]Autofac register generic instance with concrete type

I want to register a interface to a specific implementation.我想注册一个特定实现的接口。 The interface and the class both are generic instances, here it goes:接口和类都是通用实例,这里是:

This is the container registration:这是容器注册:

builder.RegisterType<ParsedStatement>()
       .As<IParsedStatement>()
       .InstancePerDependency();
builder.RegisterType<NpoiParser<ParsedStatement>>()
       .As<IParser<IParsedStatement>>()
       .InstancePerDependency();

The interface for IParser: IParser 的接口:

 public interface IParser<T> where T : class

The implementation of NpoiParser NpoiParser 的实现

 public class NpoiParser<T> : BaseParser<T>, IParser<T> where T : class

ParsedStatement class already implements the interface IParsedStatement. ParsedStatement 类已经实现了接口 IParsedStatement。 Although when i start the application I get this error from the the build of the autofac container虽然当我启动应用程序时,我从 autofac 容器的构建中得到了这个错误

System.ArgumentException: 'The type RF.Infrastructure.Parser.NpoiParser`1[RF.Domain.ValueObjects.ParsedStatement] is not assignable to service RF.Domain.Interfaces.Parser.IParser`1[[RF.Domain.Interfaces.ValueObjects.IParsedStatement, RF.Domain.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] .' System.ArgumentException: ' RF.Infrastructure.Parser.NpoiParser`1[RF.Domain.ValueObjects.ParsedStatement]类型不可分配给服务RF.Domain.Interfaces.Parser.IParser`1[[RF.Domain.Interfaces.ValueObjects.IParsedStatement, RF.Domain.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] .'

I could use a generic approach like this:我可以使用这样的通用方法:

builder.RegisterGeneric(typeof(NpoiParser<>))
       .As(typeof(IParser<>))
       .InstancePerLifetimeScope();

It works but doesn't allow me to use IParser<ParsedStatement> on the services since the NpoiParser class needs a concrete class since it uses a library and in that library only classes are permitted otherwise returns me the error "Cannot create an instance of an interface.".它可以工作,但不允许我在服务上使用IParser<ParsedStatement> ,因为 NpoiParser 类需要一个具体的类,因为它使用一个库,并且在该库中只允许类,否则返回错误“无法创建一个实例界面。”。

The stack trace for the error when using generic is the following one:使用泛型时错误的堆栈跟踪如下:

at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean wrapExceptions, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& hasNoDefaultCtor)    
at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache)    
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)   
at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)    
at Npoi.Mapper.Mapper.<Take>d__66`1.MoveNext()    
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)   
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)    
at RF.Infrastructure.Parser.NpoiParser`1.ParseFile(Stream fileToParse,  ITemplateDefinition info) in D:\Trabalho\RoyaltyFlush\royaltyflush.backend\RF.Infrastructure.Parser\NpoiParser.cs:line 52
at RF.Infrastructure.Parser.NpoiParser`1.ConvertStreamFileToObjectList(Stream fileToParse, ITemplateDefinition info) in D:\Trabalho\RoyaltyFlush\royaltyflush.backend\RF.Infrastructure.Parser\NpoiParser.cs:line 35

Any ideas on how i can register it on AutoFac with a specific class type?关于如何使用特定类类型在 AutoFac 上注册它的任何想法?

Registering NpoiParser<ParsedStatement> as IParser<IParsedStatement> is like registering apple as orange .NpoiParser<ParsedStatement>注册为IParser<IParsedStatement>就像将apple注册为orange

NpoiParser<ParsedStatement> does not implement IParser<IParsedStatement> , it only implements IParser<ParsedStatement> . NpoiParser<ParsedStatement>没有实现IParser<IParsedStatement> ,它只实现了IParser<ParsedStatement>

// Compile error
IParser<IParsedStatement> obj = new NpoiParser<ParsedStatement>();

There are two ways you could fix this:有两种方法可以解决这个问题:

  1. Inject IParser<ParsedStatement> instead of IParser<IParsedStatement> .注入IParser<ParsedStatement>而不是IParser<IParsedStatement>
  2. Change IParser<T> to covariant generic interface by using out keyword.使用out关键字将IParser<T>更改为协变通用接口 So change IParser<T> to IParser<out T> .因此,将IParser<T>更改为IParser<out T> But that requires the interface is indeed an covariant interface.但这需要接口确实是协变接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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