Типы открытых универсальных интерфейсов открытой реализации не равны типу интерфейса? - PullRequest
10 голосов
/ 21 апреля 2010

Вот тест, который, по моему мнению, должен быть пройден, но не пройден.

[TestMethod]
public void can_get_open_generic_interface_off_of_implementor()
{
    typeof(OpenGenericWithOpenService<>).GetInterfaces().First()
        .ShouldEqual(typeof(IGenericService<>));
}
public interface IGenericService<T> { }
public class OpenGenericWithOpenService<T> : IGenericService<T> { }
  1. Почему это не проходит?
  2. Учитывая Type t = typeof(OpenGenericWithOpenService<>) как мне получитьtypeof (IGenericService <>)?

Мне вообще любопытно, но если вам интересно, что я делаю, я пишу соглашение Structuremap, которое перенаправляет все интерфейсы, реализованные классом, вреализация (как одиночка).

1 Ответ

7 голосов
/ 21 апреля 2010

OpenGenericWithOpenService<T> не реализует просто произвольно IGenericService<> - он реализует IGenericService<T> для того же T, что и класс.

Лучший способ показать это - немного изменить класс:

public class OpenGenericWithOpenService<T1, T2> : IGenericService<T1> {}

Теперь важно, чтобы, когда вы спрашивали об интерфейсах, которые он реализует, вы знали, что можете преобразовать в IGenericService<T1>, но (кроме совпадений) , а не IGenericService<T2> или любую другую реализацию.

Другими словами, он не полностью открыт - он привязан к аргументу того же типа, что и класс.

Я никогда не был очень хорош в терминологии обобщения, но я надеюсь, вы понимаете, что я имею в виду. IGenericService<> - это тип, ожидающий получения аргумента типа; в этом случае у вас есть аргумент типа - это просто другой параметр типа!

Вот тест, который пройдет:

[TestMethod]
public void can_get_open_generic_interface_off_of_implementor()
{
    Type[] typeParams = typeof(OpenGenericWithOpenService<>).GetGenericArguments();
    Type constructed = typeof(IGenericService<>).MakeGenericType(typeParams);
    typeof(OpenGenericWithOpenService<>).GetInterfaces().First()            
        .ShouldEqual(constructed);
}

Если вы измените класс для реализации (скажем) IGenericService<int>, он потерпит неудачу.

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