Использование ограниченных универсальных методов расширения в отдельной сборке дает ошибку ссылки - PullRequest
5 голосов
/ 18 декабря 2008

Я создал отдельную сборку, которая будет содержать общие методы расширения, методы расширения используют классы из System.Web.dll (и других).

Когда я создаю новый проект (консольное приложение), который ссылается на сборку Utilities.dll, содержащую методы расширения, мне не нужно добавлять ссылку на System.Web.dll в новый проект, если он не использует расширение методы, расширяющие любой класс в сборке System.Web.dll (например, System.Web.UI.Control).

Когда один из методов расширения будет универсальным, все будет работать как положено. Но как только я добавлю ограничение к универсальному методу, который ограничивает его классом в сборке System.Web.dll, компилятор пожалуется, что моему новому проекту (Консольное приложение) требуется ссылка на System.Web.dll, даже если новый проект все еще ничего не использую в этой сборке.

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

Пример сборки моих методов расширения (скомпилирован как библиотека Utilities.dll<code>):</p> <pre><code>public static class StringExtensions { public static bool IsNullOrEmpty(this string value) { return string.IsNullOrEmpty(value); } } public static class ControlExtensions { // If I remove the where clause it compiles public static T FildChild<T>(this Control parent, string id) where T : Control { throw new NotImplementedException(); } }

А вот новое консольное приложение, которое не будет компилироваться (если только я не добавлю ссылку на System.Web.dll):

    static void Main(string[] args)
    {
        bool isEmpty = "Hello World!".IsNullOrEmpty();

        Console.ReadLine();
    }

<ч /> Обновление: Как отметил Марк (ниже), размещение ошибочного метода в отдельном пространстве имен решает проблему.

Но все еще остается вопрос, почему ограничение является проблемой, в то время как тип Control уже использовался в качестве параметра метода. и почему пространство имен является решением, когда я уже использую директиву вверху.

Ответы [ 2 ]

5 голосов
/ 18 декабря 2008

ну да! Для компиляции необходимо иметь возможность разрешать все в публичном / защищенном API. В противном случае он не может применить ограничение. Я полагаю, что нужно распознавать типы, чтобы увидеть, является ли метод расширения кандидатом на метод.

Вы можете попытаться поместить методы расширения в дочернее пространство имен, в котором есть "Web" - по крайней мере, тогда оно не попадет в обычный код. Я проверил , и это устраняет проблему. Рекомендуется разделять пространства имен методов расширения, чтобы вызывающая сторона могла контролировать, когда они должны находиться в области видимости.

Для выполнения также необходимо иметь возможность разрешать все, что используется внутри, но не , представленное в API. Это стандартное поведение.

1 голос
/ 18 декабря 2008

@ Марк объясняет почему. В качестве хорошей практики я бы предложил разбить все, что относится к веб-классам, на еще одну сборку, например Com.Company.Extensions.Web в дополнение к Com.Company.Extensions. Затем вы можете включить как в веб-проекты, так и только не веб-расширения в других проектах.

...