Совместное использование — это забота: использование общих проектов в ASP.NET

Для разработчиков программного обеспечения копирование и вставка некоторого кода или нескольких файлов и размещение их в нескольких местах всегда было неприятно. Есть несколько различных способов, которые вы можете использовать, чтобы избежать такого рода избыточности, но в этой статье мы сосредоточимся на одном, о котором, кажется, не слишком часто говорят: Общие проекты.

Избегайте избыточности за счет связывания

Прежде чем приступить к общим проектам, я вкратце расскажу, почему были введены сами общие проекты и как вы могли добиться аналогичного поведения до их выпуска.

В связи с тем, что в течение последних нескольких лет Visual Studio активно продвигала кроссплатформенность, возникла проблема, связанная с организацией кода, доступ к которому будет осуществляться на нескольких платформах, не сводя с ума простое копирование и вставку. Ответом на это была легендарная опция «Добавить как ссылку»:

Вы можете просто щелкнуть проект, выбрать параметр «Добавить существующий файл», а затем выбрать параметр «Добавить как ссылку», появившийся в диалоговом окне. По сути, это создаст указатель на исходный файл, который появится в обоих проектах.

Проблема с этим — это было утомительно. Вы могли выбрать только один файл за раз, и представьте, если бы вам пришлось ссылаться на несколько файлов на разных платформах? Этого достаточно, чтобы ваше запястье покалывало при мысли об этом.

Просто должен был быть лучший способ и предлагаемое решение: общие проекты.

Что такое общий проект?

Концепция общих проектов была введена в Visual Studio 2013 RC 2 и, в двух словах, позволяет вам ссылаться на весь проект, а не только на одну сборку, как в случае с библиотекой классов.

Теперь, как это работает? Есть ли в проекте все типы вещей, которые я, возможно, не захочу использовать? Как обрабатывать ссылки в общем проекте? Как насчет всего этого?

Важно отметить, что термин «общий проект» может также означать «общий блок кода», поскольку он больше функционирует как проект-заполнитель, в котором вы можете хранить весь свой код и другие файлы, такие как ресурсы. Во время компиляции любой проекты, которые ссылаются на этот общий проект, будут иметь все файлы (включая структуру папок и т. д.), включенные в них, а затем они будут скомпилированы, или, другими словами:

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

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

Использование общего проекта

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

Чтобы добавить общий проект в существующее решение, щелкните решение правой кнопкой мыши и выберите "Добавить проект", а затем выберите "Общий проект" на вкладке Visual C#:

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

Для этого примера мы создадим новый файл, который делает попытку добавления, но просто не очень хорошо:

namespace Common  
{
    public static class Math
    {
        /// 
        /// An unreliable addition method
        ///
        public static int DefunctAdd(int x, int y)
        {
            return (x + y) + 3;
        }
    }
}

Далее мы хотим добавить ссылку на это в другом проекте. Это работает аналогично тому, как вы привыкли добавлять ссылки в прошлом. Щелкните правой кнопкой мыши проект, в котором вы хотите использовать общий проект, выберите «Добавить ссылку» и выберите общий проект на вкладке «Общие проекты», которая появляется слева:

Добавив это в качестве ссылки, теперь вы можете просто использовать следующее для доступа к этому методу в ваших целевых проектах:

var result = Common.Math.DefunctAdd(3, 7);

Здесь нет ничего особенного. Это то, что ты всегда умел делать. Что ж, давайте немного оживим его, применив атрибуты условной компиляции, чтобы функция вел себя по-разному в зависимости от целевой платформы:

public static int DefunctAdd(int x, int y)  
{
#if NETCOREAPP1_1
            return (x + y) + 3;
#else
            return (x + y) + 13;
#endif
}

Поскольку этот файл будет компилироваться независимо каждым проектом, который на него ссылается, мы можем ссылаться на общий проект в двух отдельных приложениях и получать следующие результаты:

// .NET Core 1.1 
Common.DefunctAdd(3, 7); // returns 13 
// .NET Core 1.0 
Common.DefunctAdd(3, 7); // returns 23

Это довольно простой пример, но варианты использования значительно расширяются, если вы создаете кроссплатформенное приложение или вам нужно совместно использовать ресурсы (например, изображения, CSS, XAML и т. д.) между ними.

Теперь вы можете спросить себя в этот момент, зачем мне все это? Нельзя ли для этого просто использовать переносимую библиотеку классов? Да, вы абсолютно можете, но будет ли это лучшим способом решить вашу проблему?

Как обычно в мире программного обеспечения, все зависит от обстоятельств, и в следующем разделе мы сравним эти два подхода и посмотрим, чем они отличаются.

Общие проекты против переносимых библиотек классов

Ключевые различия сводятся к тому, как эти объекты компилируются и как они повторно используются:

  • Библиотеки Portable Class компилируются, как вы уже знаете и ожидаете, и единицей повторного использования является сборка (т. е. вы ссылаетесь на YourLibrary.dll в других своих проектах).
  • Общие проекты сами по себе не компилируются, а код, содержащийся в проекте, включается в каждую сборку, которая ссылается на общий проект, перед компиляцией. Следовательно, единицей повторного использования в общем проекте является фактически сам исходный код (т. е. вы ссылаетесь на «контейнер» кода, который хотите включить в другой проект).

Теперь распространенным вариантом использования общего проекта будет сценарий, в котором вам нужно создать приложение для нескольких платформ. Обычно вы можете подумать о создании переносимой библиотеки классов (PCL), но давайте посмотрим, как это можно сравнить с общим проектом:

Зачем мне использовать один другой другой?

И общие проекты, и переносимые библиотеки классов часто встречаются при создании кроссплатформенных приложений, и это правильно.

Идея совместного использования кода для нескольких проектов и потенциально разных платформ и архитектур невероятно привлекательна. Когда вы рассматриваете возможность расширения этого не только на код, но и на ресурсы, XAML, даже Javascript, CSS и другие файлы на стороне клиента, это действительно демонстрирует мощь этих концепций.

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

Поскольку общий проект охватывает большинство сценариев, в которых обычно используется переносимая библиотека классов, вот несколько вещей, которые следует учитывать перед ее использованием:

  • Важна ли сборка в вашем сценарии? Если это все, что вам нужно для общего доступа, то вполне подойдет PCL.
  • Вам нужно поделиться чем-то другим, кроме кода C#, например Javascript или другими ресурсами? Общий проект идеально подходит для этого.
  • Вам нужно несколько приложений для компиляции одного и того же кода разными способами (либо с помощью разных сборок, на которые ссылаются, либо с помощью директив)? На самом деле вы сможете сделать это только с помощью общего проекта.
  • Знаете ли вы точно, на какую версию платформы вы будете ориентироваться? Если да, то можно использовать переносимую библиотеку классов.
  • Нужно разделить код и просто не делиться всем? С общим проектом все или ничего (по крайней мере, без особых усилий, чтобы игнорировать вещи), поэтому переносимая библиотека классов позволит вам только поделитесь, что вам нужно.
  • Нужно проводить модульное тестирование всего? Переносимые библиотеки классов лучше подходят для модульного тестирования, поскольку общие проекты будут компилировать данный файл в несколько проектов (что может привести к разным результатам).

Итак, как и в большинстве случаев при создании приложений, это зависит.

Заключительные мысли по общим проектам

Табы или пробелы? Реагировать или Ангуляр? Общие проекты или переносимые библиотеки классов? Все это общие обсуждения при создании приложений или принятии связанных с ними решений, и у каждого есть свое мнение о том, что правильно.

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

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

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

Первоначально опубликовано на rion.io 22 марта 2017 г.