Autofac: тип «...» не может быть назначен службе «...». - PullRequest
0 голосов
/ 11 мая 2018

Рассмотрим следующие классы и интерфейсы:

interface IFactory<T>{}
class Factory<T> : IFactory<T>{ }

interface IEntity{}
class Entity : IEntity{ }

Я бы хотел, чтобы Autofac разрешил IFactory<IEntity> до Factory<Entity> следующим образом:

b.RegisterType<Factory<Entity>>().As<IFactory<IEntity>>();

Но я получаю следующее исключение(сокращенно для ясности):

The type 'Factory`1[Entity]' is not assignable to service 'IFactory`1[[IEntity]]'

Почему и как эта проблема может быть решена?Или я пытаюсь что-то «не так»?

Я кратко изучил RegisterGeneric, но я не думаю, что это применимо здесь;Кроме того, потому что выше, это просто пример.В других случаях я могу захотеть определить другой компонент для IFactory<IEntity>.

1 Ответ

0 голосов
/ 11 мая 2018

Это не проблема Autofac - это общая проблема. То же самое вы увидите в простой программе на C #:

public class Program 
{
    public static void Main() 
    {
        IFactory<IEntity> factory = new Factory<Entity>();
    }
}

Большинство универсальных интерфейсов инвариант - аргументы типа должны точно совпадать. Некоторые из них ковариантны как IEnumerable<T>, что позволяет вам написать:

IEnumerable<object> objects = new List<string>();

и некоторые контравариантные , такие как IComparer<T>, что позволяет вам написать:

IComparer<string> = Comparer<object>.Default;

Ковариантные интерфейсы позволяют только их типовым параметрам выходить из реализации (например, через возвращаемые типы). Контравариантные интерфейсы позволяют только своим типовым параметрам входить в реализацию (например, через обычные параметры). Это становится незаметным, когда у вас есть параметры-делегаты, которые сами принимают значения и т. Д., Но мы пока проигнорируем это ...

Похоже, ваш IFactory<T> должен быть ковариантным - так что вы просто измените объявление следующим образом:

interface IFactory<out T>{}

В этот момент код компилируется, и я надеюсь , что Autofac тоже справится с этим. Это требует, чтобы ваш интерфейс никогда не использовал T в качестве входных данных. (Мы не можем сказать, так как вы не показали ни одного члена интерфейса.)

Подробнее об общей дисперсии см. В документации MS .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...