IGet.GetAll 1.0.0

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

// Install IGet.GetAll as a Cake Tool
#tool nuget:?package=IGet.GetAll&version=1.0.0                

IGet.GetAll

Extends IGet. Get an IEnumerable of class instances (with their dependencies injected) via i.GetAll<IMyInterface>() or i.GetAll<MyBaseClass>().

Idea: create a generic notification publisher and use it like i.Get<NotificationPublisher<NotificationA>>().Publish(notification) instead of mediatR.Publish(notification).

using IGetAll;
serviceCollection.AddIGet();
serviceCollection.AddIGetAll(new [] { typeof(Startup).Assembly, ... });

Why?

IGet gets single classes, but cannot provide multiple in one call. If you like MediatR's INotification-INotificationHandler combination then you will probably feel the need for something that automatically collects INotificationHandlers - that is one of the things that i.GetAll<T>() can do - it has the following benefits:

  • you declare whatever interfaces and base classes you like; this package does not force you to use pre-defined interfaces.
  • after i.GetAll<T>() you explicitly show how you handle exceptions, making your code easier to understand.
  • after i.GetAll<T>() you explicitly show that you use Task.WhenAll or foreach with await (or synchronous code).

Also note: no matter how complicated your interfaces or generic base classes are - think about IMyInterface<SomeClass, NestedBaseClass<AnotherClass, AndMore>> - no additional configuration is needed.

About performance

Each time you use i.GetAll<T>() for a new type T the collected Type[] is stored in a ConcurrentDictionary so that when you call i.GetAll<T>() next time for the same type T, no assembly scanning is done.

Example

Declare an interface you like:

public interface INotificationHandler<TNotification>
{
    Task HandleAsync(TNotification notification, CancellationToken cancellationToken);
}

Implement the interface:

public class NotificationA { }

public class HandlerA1 : INotificationHandler<NotificationA>
{
    private readonly ILogger<HandlerA1> _logger;
    public HandlerA1(ILogger<HandlerA1> logger)
    {
        _logger = logger;
    }
    public async Task HandleAsync(NotificationA notification, CancellationToken cancellationToken)
    {
        // do stuff
    }
}

public class HandlerA2 : INotificationHandler<NotificationA>
{
    private readonly IConnectionFactory _connectionFactory;
    public HandlerA2(IConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }
    public async Task HandleAsync(NotificationA notification, CancellationToken cancellationToken)
    {
        // do stuff
    }
}

public class NotificationB { }

public class HandlerB1 : INotificationHandler<NotificationB>
{
    private readonly ILogger<Handler1> _logger;
    public HandlerB1(ILogger<Handler1> logger)
    {
        _logger = logger;
    }
    public async Task HandleAsync(NotificationB notification, CancellationToken cancellationToken)
    {
        // do stuff
    }
}

Create a generic notification publisher for all your notification types:

public class NotificationPublisher<TNotification> where TNotification : notnull
{
    private readonly ILogger _logger;
    private readonly IGet i;

    public NotificationPublisher(IGet iget, ILogger logger)
    {
        _logger = logger;
        i = iget;
    }

    public async Task Publish(TNotification notification, CancellationToken cancellationToken = default)
    {
        foreach (var handler in i.GetAll<INotificationHandler<TNotification>>())
        {
            try
            {
                await handler.HandleAsync(notification, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in {handlerType} for {notificationKeyValuePairs}.", handler.GetType().FullName, notification.ToKeyValuePairsString());
            }
        }
    }
}

Publish notifications:

// invokes HandlerA1 and HandlerA2:
await i.Get<NotificationPublisher<NotificationA>>().Publish(notificationA);
// invokes HandlerB1:
await i.Get<NotificationPublisher<NotificationB>>().Publish(notificationB);

Try it out

The examples above give an idea of how you can be creative with IGet and IGet.GetAll. Share your own examples online to spread the word about IGet and IGet.GetAll.

If you're interested in the source code of this library, then use IGet in Visual Studio and press F12 with your cursor on the AddIGetAll() extension method.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

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.5 1,457 12/13/2023
1.0.4 5,059 4/12/2023
1.0.3 869 3/29/2023
1.0.2 212 3/21/2023
1.0.1 203 3/20/2023
1.0.0 195 3/19/2023
1.0.0-alpha 127 3/19/2023

v1.0.*: updates of the readme.