Visual Studio Intellisense не может разрешить мои методы расширения с ограничениями общего типа - PullRequest
0 голосов
/ 10 января 2019

Я создаю Фабрику для компонентов моего приложения на основе универсальных интерфейсов. Я реализовал один метод фабрики для создания компонентов и один метод 'Init' (расширение) для внедрения зависимостей в каждый тип компонента.

Код компилируется и запускается, как и ожидалось. В любом случае Visual Studio (версии 2015 и 2017) не может правильно отображать мои методы 'Init' на объектах компонентов. Под «неудачами» я подразумеваю, что Visual Studio 2015 их вообще не показывает. Visual Studio 2017 ведет себя немного по-другому, поскольку, по крайней мере, он показывает их, но он также показывает неправильные и не может динамически разрешать универсальные типы.

Следующий код является упрощением моего фактического кода, но все же достаточно, чтобы воспроизвести проблему.

Это мои компоненты интерфейсов:

public interface IBaseComponent { }
public interface IComponent : IBaseComponent { }
public interface IComponent<TDependency> : IBaseComponent { }
public interface IComponent<TDependency1, TDependency2> : IBaseComponent { }    

Это заводской код:

public static class ComponentFactory
{
    //Method to create the component
    public static T CreateComponent<T>() where T : IBaseComponent
    {
        //return instance of T
    }

    //Extension method to initialize the component
    public static T Init<T>(this T component) where T : IComponent
    { //Do stuff and return component.. }

    //Extension method to initialize the component and inject depenencies
    public static T Init<T, TDependency>(this T component, TDependency dependency) where T : IComponent<TDependency>
    { //Do stuff and return component.. }

    //Extension method to initialize the component and inject depenencies
    public static T Init<T, TDependency1, TDependency2>(this T component, TDependency1 dependency1, TDependency2 dependency2) where T : IComponent<TDependency1, TDependency2>
    { //Do stuff and return component.. }
}

Эти классы реализуют интерфейсы IComponent:

public class MyComponent : IComponent { }
public class MyComponent1A : IComponent<MyComponent> { }
public class MyComponent1B : IComponent<MyComponent> { }
public class MyComponent2 : IComponent<MyComponent1A, MyComponent1B> { }

И вот как я называю фабричные методы:

MyComponent mC = ComponentFactory.CreateComponent<MyComponent>().Init();
MyComponent1A mC1A = ComponentFactory.CreateComponent<MyComponent1A>().Init(mC);
MyComponent1B mC1B = ComponentFactory.CreateComponent<MyComponent1B>().Init(mC);
MyComponent2 mC2 = ComponentFactory.CreateComponent<MyComponent2>().Init(mC1A, mC1B);

Я ожидаю, что Visual Studio предложит мне правильный метод Init для каждого класса компонентов, например:

MyComponent   => Init<MyComponent>(this MyComponent component);
MyComponent1A => Init<MyComponent1A, MyComponent>(this MyComponent1A component, MyComponent dependency);
MyComponent1B => Init<MyComponent1B, MyComponent>(this MyComponent1B component, MyComponent dependency);
MyComponent2  => Init<MyComponent2, MyComponent1A, MyComponent1B>(this MyComponent2 component, MyComponent1A dependency1, MyComponent1B dependency2);

Вместо этого Visual Studio 2015 может показывать только метод Init для MyComponent, но не отображает методы для MyComponent1A, MyComponent1B и MyComponent2

Visual Studio 2017 с любопытством показывает все методы Init для класса MyComponent и только последние два для остальных трех классов. Он также оставляет имена обобщенных типов вместо того, чтобы заменять их правильными для фактического класса.

MyComponent => Init<MyComponent>(this MyComponent component); /*Correct*/
MyComponent => Init<MyComponent, TDependency>(this MyComponent component, TDependency dependency); /*Wrong*/
MyComponent => Init<MyComponent, TDependency1, TDependency2>(this MyComponent component, TDependency1 dependency, TDependency2 dependency); /*Wrong*/

MyComponent1A => Init<MyComponent1A, TDependency>(this MyComponent1A component, TDependency dependency); /*Correct*/
MyComponent1A => Init<MyComponent1A , TDependency1, TDependency2>(this MyComponent1A component, TDependency1 dependency, TDependency2 dependency); /*Wrong*/

//etc..

Очевидно, что из-за ограничений параметров типа, которые я наложил на методы расширения, Wrong те даже не компилируются.

У меня такое ощущение, что на VS2015 я некоторое время видел, как он работает, и я не уверен, что проблема в моем коде или в VS.

Отсутствующее предложение Intellisense почти не соответствует цели моего кода.

Кто-нибудь может заставить его появиться?

Что-то не так с моим кодом, которого я не вижу, или какие-то изменения, которые я мог бы сделать, чтобы избежать этой проблемы?

Спасибо

...