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:
public interface IParser<T> where T : class
The implementation of NpoiParser
public class NpoiParser<T> : BaseParser<T>, IParser<T> where T : class
ParsedStatement class already implements the interface IParsedStatement. Although when i start the application I get this error from the the build of the autofac container
System.ArgumentException: 'The type
RF.Infrastructure.Parser.NpoiParser`1[RF.Domain.ValueObjects.ParsedStatement]
is not assignable to serviceRF.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.".
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?
Registering NpoiParser<ParsedStatement>
as IParser<IParsedStatement>
is like registering apple as orange.
NpoiParser<ParsedStatement>
does not implement IParser<IParsedStatement>
, it only implements IParser<ParsedStatement>
.
// Compile error
IParser<IParsedStatement> obj = new NpoiParser<ParsedStatement>();
There are two ways you could fix this:
IParser<ParsedStatement>
instead of IParser<IParsedStatement>
.IParser<T>
to covariant generic interface by using out
keyword. So change IParser<T>
to IParser<out T>
. But that requires the interface is indeed an covariant interface.