Монорепозиторий с C#: организация кода для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Монорепозиторий с C#: организация кода для начинающих

В современной разработке на C# (.NET) рано или поздно встает вопрос: как организовать код, когда у вас несколько проектов — библиотека классов, веб-API, консольное приложение, тесты? Многие начинающие разработчики создают отдельные репозитории для каждой части, что приводит к путанице в версиях и зависимостях. Альтернатива — монорепозиторий (monorepo). В этой статье мы разберем, что такое монорепозиторий, как его настроить в C# и почему он упрощает жизнь новичкам.

Что такое монорепозиторий?

Монорепозиторий — это подход, при котором весь код нескольких связанных проектов хранится в одном репозитории Git. Например, у вас может быть общая библиотека MyApp.Shared, веб-приложение MyApp.Web и консольный инструмент MyApp.Cli — все в одной папке, с одним .sln файлом.

В контексте C# (.NET) монорепозиторий обычно означает одно Visual Studio Solution, содержащее несколько проектов. Это особенно удобно для:

  • Совместного использования кода (через Project References, а не NuGet пакеты).
  • Единого процесса сборки и CI/CD.
  • Упрощения работы с версиями (одна ветка — все изменения сразу).

Преимущества монорепозитория для начинающих

Если вы только начинаете изучать C#, монорепозиторий поможет избежать типичных ошибок:

  • Простота навигации — все проекты в одном месте, не нужно переключаться между репозиториями.
  • Мгновенная связь — изменение в библиотеке сразу видно в зависимых проектах.
  • Единый стиль — можно настроить один .editorconfig или Directory.Build.props для всех проектов.
  • Легко запускать тесты — одной командой dotnet test проверяется всё решение.

Создание структуры монорепозитория: пошаговое руководство

Шаг 1. Создаем корневую папку и решение

Откройте терминал и выполните:

mkdir MyMonorepo
cd MyMonorepo
dotnet new sln -n MyApp

Теперь у вас есть файл MyApp.sln — это точка входа для Visual Studio или Rider.

Шаг 2. Добавляем проекты

Создадим три проекта: библиотеку классов, веб-API и консольное приложение. Для удобства поместим их в подпапки src:

mkdir src
cd src
dotnet new classlib -n MyApp.Shared
dotnet new webapi -n MyApp.Web
dotnet new console -n MyApp.Cli
cd ..

Теперь привяжем их к решению:

dotnet sln add src/MyApp.Shared/MyApp.Shared.csproj
dotnet sln add src/MyApp.Web/MyApp.Web.csproj
dotnet sln add src/MyApp.Cli/MyApp.Cli.csproj

Шаг 3. Настраиваем зависимости между проектами

Допустим, MyApp.Web и MyApp.Cli используют классы из MyApp.Shared. Вместо того чтобы публиковать библиотеку в NuGet, просто добавьте Project Reference:

dotnet add src/MyApp.Web/MyApp.Web.csproj reference src/MyApp.Shared/MyApp.Shared.csproj
dotnet add src/MyApp.Cli/MyApp.Cli.csproj reference src/MyApp.Shared/MyApp.Shared.csproj

Теперь в файле MyApp.Web.csproj появится секция:

<ItemGroup>
  <ProjectReference Include="..\MyApp.Shared\MyApp.Shared.csproj" />
</ItemGroup>

Шаг 4. Пишем общий код

В проекте MyApp.Shared создадим простой класс:

// src/MyApp.Shared/GreetingService.cs
namespace MyApp.Shared;

public class GreetingService
{
    public string GetGreeting(string name) => $"Привет, {name}! Добро пожаловать в монорепозиторий.";
}

Теперь используем его в консольном приложении:

// src/MyApp.Cli/Program.cs
using MyApp.Shared;

var service = new GreetingService();
Console.WriteLine(service.GetGreeting("Алексей"));

И в веб-API (например, в контроллере):

// src/MyApp.Web/Controllers/HomeController.cs
using Microsoft.AspNetCore.Mvc;
using MyApp.Shared;

[ApiController]
[Route("api/[controller]")]
public class HomeController : ControllerBase
{
    [HttpGet("{name}")]
    public IActionResult Get(string name)
    {
        var service = new GreetingService();
        return Ok(new { message = service.GetGreeting(name) });
    }
}

Шаг 5. Добавляем тесты

Тесты тоже лучше хранить в монорепозитории. Создадим папку tests и проект с тестами:

mkdir tests
cd tests
dotnet new xunit -n MyApp.Tests
cd ..
dotnet sln add tests/MyApp.Tests/MyApp.Tests.csproj
dotnet add tests/MyApp.Tests/MyApp.Tests.csproj reference src/MyApp.Shared/MyApp.Shared.csproj

Напишем простой тест:

// tests/MyApp.Tests/GreetingServiceTests.cs
using Xunit;
using MyApp.Shared;

public class GreetingServiceTests
{
    [Fact]
    public void GetGreeting_ReturnsCorrectMessage()
    {
        var service = new GreetingService();
        var result = service.GetGreeting("Мир");
        Assert.Contains("Мир", result);
    }
}

Дополнительные советы по организации

Используйте Directory.Build.props

Чтобы не дублировать общие настройки (например, версию .NET, nullable), создайте в корне файл Directory.Build.props:

<Project>
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>                

Блоги

Рекомендаций по книгам