Autofa c регистр generi c экземпляр с конкретным типом - PullRequest
1 голос
/ 02 апреля 2020

Я хочу зарегистрировать интерфейс для конкретной реализации c. Интерфейс и класс оба являются обобщенными c экземплярами, вот так:

Это регистрация контейнера:

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

Интерфейс для IParser:

 public interface IParser<T> where T : class

Реализация NpoiParser

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

Класс ParsedStatement уже реализует интерфейс IParsedStatement. Хотя, когда я запускаю приложение, я получаю эту ошибку из сборки контейнера autofa c

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]]».

Я мог бы использовать обобщенный c подход, подобный следующему:

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

Он работает, но не позволяет мне использовать IParser<ParsedStatement> на сервисах, так как класс NpoiParser нужен конкретный класс, так как он использует библиотеку, и в этой библиотеке разрешены только классы, в противном случае возвращается сообщение об ошибке «Невозможно создать экземпляр интерфейса».

Трассировка стека для ошибки при использовании generi c следующий:

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

Есть идеи, как мне зарегистрировать его в AutoFa c с указанным c типом класса?

1 Ответ

2 голосов
/ 02 апреля 2020

Регистрация NpoiParser<ParsedStatement> как IParser<IParsedStatement> аналогична регистрации apple как orange .

NpoiParser<ParsedStatement> не реализует IParser<IParsedStatement>, он реализует только IParser<ParsedStatement>.

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

Существует два способа исправить это:

  1. Введите IParser<ParsedStatement> вместо IParser<IParsedStatement>.
  2. Измените IParser<T> на ковариантный универсальный c интерфейс , используя ключевое слово out. Так что измените IParser<T> на IParser<out T>. Но для этого требуется, чтобы интерфейс действительно был ковариантным интерфейсом.
...