J4JSoftware.TypeUtilities 1.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package J4JSoftware.TypeUtilities --version 1.2.0
NuGet\Install-Package J4JSoftware.TypeUtilities -Version 1.2.0
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="J4JSoftware.TypeUtilities" Version="1.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add J4JSoftware.TypeUtilities --version 1.2.0
#r "nuget: J4JSoftware.TypeUtilities, 1.2.0"
#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.
// Install J4JSoftware.TypeUtilities as a Cake Addin
#addin nuget:?package=J4JSoftware.TypeUtilities&version=1.2.0

// Install J4JSoftware.TypeUtilities as a Cake Tool
#tool nuget:?package=J4JSoftware.TypeUtilities&version=1.2.0

J4JSoftware.TypeUtilities

Provides mechanisms for filtering types during dependency injection registration. While developed to work with Autofac the filtering routines should work with other DI frameworks as well.

The library repository is available on github.

That same link also provides documentation of how these utilities are used by my Autofac-based DI/IHost library.

Overview

I love Autofac, a powerful dependency injection library for C#. I use it in almost all of my projects. It makes egistering concrete types as either specific interface implementations or as themselves a snap.

There are a few ways its use can be simplified, though, in some use cases. That's what this library aims to do: make it relatively straightforward to specify various kinds of type filter conditions, so you can register all the classes that match the conditions at once.

I've designed this library so that it is not dependent on Autofac. While I've only implemented its capabilities for Autofac, you are welcome to adapt them to whatever DI framework you use.

Example

private void SetupDependencyInjection( HostBuilderContext hbc, ContainerBuilder builder )
{
    var typeTests = new TypeTests<IImportData>()
                    .AddTests( PredefinedTypeTests.NonAbstract )
                    .AddTests( PredefinedTypeTests.NonGeneric )
                    .AddTests( new FilterTypeTester<IImportData>( RequireSheetTypeAttribute ) );

    builder.RegisterTypeAssemblies<IImportData>( typeTests );
}

private bool RequireSheetTypeAttribute( Type toCheck ) =>
    toCheck.GetCustomAttribute<SheetTypeAttribute>( false ) != null;

This sequence will register all the concrete types in the assembly which defines the IImportData interface which:

  • are not abstract
  • are not generic
  • are decorated with a non-inherited SheeteTypeAttribute

Architecture

The tests are executed by an instance of TypeTests, which implements the ITypeTester interface. That interface contains a single method call, which returns true if a supplied type meets all the requirements and false if it doesn't:

public interface ITypeTester
{
    bool MeetsRequirements( Type toTest );
}

TypeTesters implements the same interface, iterating over all the individual tests that were added to its instance. Those tests are added by calling one or more extension methods:

Extension Method Purpose Arguments
AddPredefinedTests adds one or more predefined tests (see below) one or more predefined tests
HasConstructorArgs requires a public instance (i.e., not-static) constructor taking a specified sequence of arguments one or more types
DecoratedWith requires the type be decorated with an attribute. You specify the attribute's type, so if you specify a type which isn't an attribute all types will be rejected/filtered out. the required attribute type, and a flag as to whether inherited attributes should be searched (defaults to false)
FilteredBy requires a type to meet a user-defined test a method reference which accepts a Type argument and returns true or false
AddTests adds one or more instances of ITypeTester allows the addition of custom-designed tests

Predefined Tests

There are a number of tests I use quite frequently so I created predefined tests that are characterized by the PredefinedTypeTests enum:

Enum Value Purpose
NonAbstract requires that the type not be abstract
NonGeneric requires that the type not be generic
ParameterlessConstructor requires that the type have a public instance (i.e., non-static) constructor which accepts no arguments
OnlyJ4JLoggerRequired requires that the type have a public instance (i.e., non-static) constructor which requires only one argument, an instance implementing my logging system, IJ4JLogger (for more information, see the IJ4JLogger documentation)

Creating Your Own Test

Creating a custom test is easy: just create a class which implements ITypeTester:

public interface ITypeTester
{
    bool MeetsRequirements( Type toTest );
}
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on J4JSoftware.TypeUtilities:

Package Downloads
J4JSoftware.DependencyInjection

provides customized IHostBuilder and IHost classes for simplified configuration

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.1 245 4/11/2023
1.3.0 187 4/4/2023
1.2.0 347 12/27/2022
1.1.1 414 2/28/2022
1.1.0 498 11/12/2021
1.0.0 1,632 9/28/2021

updated to net7