TypeHarvester 1.0.3

dotnet add package TypeHarvester --version 1.0.3
                    
NuGet\Install-Package TypeHarvester -Version 1.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TypeHarvester" Version="1.0.3">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TypeHarvester" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="TypeHarvester">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TypeHarvester --version 1.0.3
                    
#r "nuget: TypeHarvester, 1.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TypeHarvester@1.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TypeHarvester&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=TypeHarvester&version=1.0.3
                    
Install as a Cake Tool

TypeHarvester

Overview

TypeHarvester is an incremental Roslyn source generator that scans assemblies for types marked with specified attributes and generates a strongly-typed cache class named TypesByAttributes.

This cache provides several overloads of the Get method, allowing you to retrieve all types annotated with one or more attributes without using reflection at runtime.


Why Use It?

TypeHarvester exists to eliminate reflection-based type discovery and the numerous issues that come with it:

  • The target assembly may not be loaded into the AppDomain when reflection runs.
  • Version conflicts or isolation between different AssemblyLoadContexts.
  • Assemblies missing from AppDomain.CurrentDomain.GetAssemblies() enumeration.
  • ReflectionTypeLoadException due to inaccessible types.
  • Problems with dynamic or reflection-only assemblies.
  • Attributes inaccessible due to missing dependency assemblies.
  • Types trimmed by the .NET linker (Trimming in .NET Core+).

By collecting metadata at compile time, TypeHarvester prevents these leaky abstractions of reflection and provides a fast, reliable, compile-time cache of attributed types.


Installation

In your project’s .csproj:

<ItemGroup>
  <PackageReference Include="TypeHarvester" Version="latest">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets> analyzers;</IncludeAssets>
  </PackageReference>
  <AdditionalFiles Include="codegen.config.json" />
</ItemGroup>

Then, place a codegen.config.json file in your project root:

{
	"CollectTypesWithAttributes": {
		"Attributes": [
			"TypeHarvester.Debug.Dependency.MyAttribute"
		],
		"NamespaceForGenerations": "TypeHarvester.Debug",
		"CollectToCache": false,
		"Partial": false
	}
}

Configuration Explained

Setting Description
Attributes List of attribute types to collect.
NamespaceForGenerations Namespace for generated code. Must match your stub file’s namespace. If omitted, code is generated in the global namespace (not recommended).
CollectToCache If true, collected data is stored in assembly metadata instead of generating code. Used for dependent projects.
Partial If true, generated class and methods are marked as partial to support IntelliSense fixes.

Multi-Project Setup

  • For dependent projects (where you just collect attributed types):
    Set "CollectToCache": true and omit NamespaceForGenerations.
  • For the top-level project (where code is generated):
    Set "CollectToCache": false and specify NamespaceForGenerations.

This way, TypeHarvester collects attributed types from all projects and consolidates them into a single generated class in the top-level project.


IntelliSense Desync Fix

If IntelliSense reports that the generated class does not exist (but build succeeds), apply this workaround:

  1. In codegen.config.json, set "Partial": true.
  2. Add a stub file manually:
    namespace TypeHarvester.Debug;
    
    using System;
    using System.Collections.Generic;
    
    internal static partial class TypesByAttributes
    {
     internal static partial IEnumerable<Type> Get<TAttribute>();
     internal static partial IEnumerable<Type> Get<TAttribute1, TAttribute2>();
     internal static partial IEnumerable<Type> Get<TAttribute1, TAttribute2, TAttribute3>();
     internal static partial IEnumerable<Type> Get(params Type[] attributeTypes);
    }
    


Общее описание

TypeHarvester — это инкрементальный Roslyn-генератор исходного кода, который находит все типы, помеченные указанными атрибутами, и генерирует класс-кэш TypesByAttributes.

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


Зачем это нужно?

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

  • Сборка с нужным типом может не быть загружена в AppDomain в момент вызова.
  • Конфликты версий сборок или изоляция в разных AssemblyLoadContext.
  • Отсутствие нужных сборок в AppDomain.CurrentDomain.GetAssemblies().
  • Ошибка ReflectionTypeLoadException при частичной недоступности типов.
  • Проблемы с динамическими или reflection-only сборками.
  • Недоступность атрибутов из-за не загруженных зависимых сборок.
  • Удаление типов оптимизатором (Trimming) в .NET Core+.

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


Подключение

В .csproj проекта:

<ItemGroup>
  <PackageReference Include="TypeHarvester" Version="latest">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets> analyzers;</IncludeAssets>
  </PackageReference>
  <AdditionalFiles Include="codegen.config.json" />
</ItemGroup>

Создайте в корне проекта файл codegen.config.json:

{
	"CollectTypesWithAttributes": {
		"Attributes": [
			"TypeHarvester.Debug.Dependency.MyAttribute"
		],
		"NamespaceForGenerations": "TypeHarvester.Debug",
		"CollectToCache": false,
		"Partial": false
	}
}

Пояснение параметров

Параметр Описание
Attributes Список атрибутов, по которым будут собираться типы.
NamespaceForGenerations Пространство имён для сгенерированного кода. Должно совпадать с пространством имён stub-файла. Если отсутствует — генерация идёт в глобальный неймспейс (не рекомендуется).
CollectToCache Если true, данные сохраняются в метаданные сборки, а не генерируется код. Используется в зависимых проектах.
Partial Если true, код будет сгенерирован как partial для устранения ошибок IntelliSense.

Многопроектная схема

  • В зависимых проектах:
    "CollectToCache": true, параметр NamespaceForGenerations можно опустить.
  • В основном (топ-левел) проекте:
    "CollectToCache": false и обязательно указать NamespaceForGenerations.

Таким образом, генератор соберёт типы из всех подключённых проектов и создаст единый класс-кэш в основном проекте.


Исправление ошибки IntelliSense

Если IntelliSense жалуется на отсутствие класса (при этом сборка успешно компилируется):

  1. Установите "Partial": true в конфиге.
  2. Добавьте stub-файл:
    namespace TypeHarvester.Debug;
    
    using System;
    using System.Collections.Generic;
    
    internal static partial class TypesByAttributes
    {
     internal static partial IEnumerable<Type> Get<TAttribute>();
     internal static partial IEnumerable<Type> Get<TAttribute1, TAttribute2>();
     internal static partial IEnumerable<Type> Get<TAttribute1, TAttribute2, TAttribute3>();
     internal static partial IEnumerable<Type> Get(params Type[] attributeTypes);
    }
    
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 316 11/11/2025
1.0.2 212 11/5/2025
1.0.1 288 10/23/2025 1.0.1 is deprecated because it has critical bugs.
1.0.0 292 10/23/2025 1.0.0 is deprecated because it has critical bugs.