Escape Catch-22 с атрибутами расширения в.NET 2.0

Как может одна сборка.NET, ориентированная одновременно на 2.0, 3.0, 3.5, 4.0 и 4.5, поддерживать методы расширения для потребителей C# и VB.NET?

Стандартное предложение состоит в том, чтобы добавить это:

namespace System.Runtime.CompilerServices
{
  public sealed class ExtensionAttribute : Attribute { }
}

Этот подход был предложен более чем одним сотрудником Microsoft и даже был представлен в журнале MSDN. Многие блоггеры называют его "безболезненным".

О, за исключением того, что это вызовет ошибку компилятора из проекта VB.NET, ориентированного на.NET 3.5 или выше.

Авторы Microsoft.Core.Scripting.dll выяснили это и изменили "public" на "internal".

namespace System.Runtime.CompilerServices
{
  internal sealed class ExtensionAttribute : Attribute { }
}

Который, казалось, решил проблему совместимости VB.

Поэтому я доверительно использовал этот подход для последней версии (3.2.1) широко используемой библиотеки ImageResizing.Net.

Но затем мы начинаем получать эту ошибку компилятора ( оригинальный отчет), более или менее случайным образом, для определенных пользователей, ориентированных на.NET 3.5+.

Error 5 Missing compiler required member
'System.Runtime.CompilerServices.ExtensionAttribute..ctor'

Поскольку компилятор MSBuild/VisualStudio, по-видимому, не заботится о правилах определения границ при разрешении конфликтов имен, а порядок ссылок на сборки играет не совсем документально подтвержденную роль, я не до конца понимаю, почему и когда это происходит.

Есть несколько хитрых обходных путей, таких как изменение пространства имен сборки, воссоздание файла проекта, удаление / чтение System.Core и работа с целевой версией.NET framework. К сожалению, ни один из этих обходных путей не является 100% (кроме псевдонимов, но это недопустимая боль).

Как я могу это исправить, пока

  1. Постоянная поддержка использования метода расширения в сборке,
  2. Постоянная поддержка.NET 2.0/3.0
  3. Не требует нескольких сборок для каждой версии.NET Framework.

Или есть исправление, заставляющее компилятор обращать внимание на правила области видимости?

Похожие вопросы по SO, которые не отвечают на этот вопрос

1 ответ

Решение

Мы столкнулись с той же проблемой с IronPython. http://devhawk.net/2008/10/21/the-fifth-assembly/

В итоге мы переместили нашу собственную версию ExtensionAttribute в его собственную сборку. Таким образом, клиенты могут выбирать между ссылками на нашу пользовательскую сборку ExtensionAttribute или System.Core, но не на оба!

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

Учитывая жесткое требование поддержки.NET 2.0, я думаю, что лучшим вариантом будет просто не использовать методы расширения вообще. Я не знаком с проектом ImageResizer, но, похоже, это было недавнее изменение в ImageResizer. Насколько возможно было бы изменить методы расширения на традиционные статические методы? Мы действительно думали об этом для IronPython/DLR, но это было неосуществимо (в тот момент мы были объединены с LINQ, и LINQ широко использовала методы расширения по существу для всего его существования).

Другие вопросы по тегам