IGet 1.1.1
See the version list below for details.
dotnet add package IGet --version 1.1.1
NuGet\Install-Package IGet -Version 1.1.1
<PackageReference Include="IGet" Version="1.1.1" />
paket add IGet --version 1.1.1
#r "nuget: IGet, 1.1.1"
// Install IGet as a Cake Addin #addin nuget:?package=IGet&version=1.1.1 // Install IGet as a Cake Tool #tool nuget:?package=IGet&version=1.1.1
IGet
Instantiate classes that are NOT in your service collection via i.Get<Class>()
. Idea: use i.Get<Handler>().Handle(request)
instead of mediatR.Send(request)
- for less code (in total) and more freedom.
serviceCollection.AddIGet();
Why?
Having MediatR working is nice. You might, however, like IGet better:
- you don't need to implement any interface for your handlers.
- creating a request class is optional.
- have compile-time checks that all handlers exist.
- use editor shortcuts to jump to a handler method immediately.
- have a shorter StackTrace in case of an error.
- have more control for designing complex processes.
- etc.
IGet has only one responsibility - instantiating classes with their dependencies injected - but with this you can create MediatR-like structures easily. A basic IRequest-IRequestHandler structure needs less code if you use IGet and complex structures such as INotification-INotificationHandler are completely under your control.
Declaring a handler
Example 1
There is no need to implement IRequest
and IRequestHandler<Request>
or IRequest<Result>
and IRequestHandler<Request, Result>
. Choose another method name and use value type parameters if you want.
public class MyHandler
{
private IConnectionFactory _connectionFactory;
public MyHandler(IConnectionFactory connectionFactory)
{
_connectionFactory = connectionFactory;
}
public async Task<MyResult> ChooseASignature(int id)
{
// do something
}
}
Example 2
Do you prefer synchronous code if possible? That's allowed!
public class MyHandler
{
private ILogger<MyHandler> _logger;
public MyHandler(ILogger<MyHandler> logger)
{
_logger = logger;
}
public void Handle()
{
// do something
}
}
Sending a request
In the examples below i
is the IGet
instance where you call Get
on. (Like mediator
might have been the name of the variable for a IMediator
instance where you called Send
on.)
Example 1
var result = i.Get<MyHandler>().AnyRandomSignature(1);
Example 2
var handler = i.Get<MyHandler>();
handler.Handle();
Example 3
var result = await i.Get<MyHandler>().HandleAsync(new MyRequest
{
Id = 2
});
Example 4
var result = i.Get<MyHandler>().Handle(request);
Because you get the handler via generics, your code is type-checked by the compiler - therefore you know that each request has a handler immediately. Also, you can place your cursor on the class's method and press F12
to quickly navigate to the method declaration.
More complex scenarios
Example 1
Handlers may get other handlers to do stuff for them, like validation, pre-processing and post-processing.
var result = await i.Get<MoreComplexHandler>().Handle(request);
public class MoreComplexHandler
{
private ILogger<MoreComplexHandler> _logger;
private IGet i;
public MoreComplexHandler(IGet iget, ILogger<MoreComplexHandler> logger)
{
_logger = logger;
i = iget;
}
public Result<WhatWasAskedFor> Handle(Request request)
{
try
{
var validationResult = i.Get<Validator>().Validate(request);
if (!validationResult.IsValid)
{
return Result.Fail<WhatWasAskedFor>(validationResult.Message);
}
i.Get<PreProcessor>().Prepare(request);
var whatWasAskedFor = i.Get<MainProcessor>().Handle(request);
try
{
i.Get<PostProcessor>().DoLessImportantStuffWith(request, whatWasAskedFor);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "PostProcessor failed for request {requestId}.", request.Id);
}
return Result.Success(whatWasAskedFor);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error for request {requestId}.", request.Id);
return Result.Fail<WhatWasAskedFor>("Something went wrong. Try again later.");
}
}
}
Example 2
The functionality of MediatR's INotification-INotificationHandler combination can be created via something like this:
await i.Get<NotificationPublisher>().PublishAsync(notification);
public class NotificationPublisher
{
private IGet i;
public NotificationPublisher(IGet iget)
{
i = iget;
}
public async Task PublishAsync(Notification notification)
{
try
{
await i.Get<FirstHandler>().HandleAsync(notification);
}
catch { }
try
{
await i.Get<SecondHandler>().HandleAsync(notification);
}
catch { }
try
{
i.Get<ThirdHandler>().Handle(notification);
}
catch { }
}
}
Notes:
- Exceptions should be logged in the
catch
blocks. - Let's say that you have several handlers that implement
INotificationHandler<ChallengeAccepted>
and via reflection you get all those handlers as aType[]
(in astatic
property of typeLazy<Type[]>
). Then usei.Get<T>(type)
for instantiating thetype
and casting it toT
:
foreach (Type handlerType in LazyChallengeAcceptedNotificationHandlers)
{
try
{
var handler = await i.Get<INotificationHandler<ChallengeAccepted>>(handlerType);
await handler.Handle(challengeAcceptedNotification);
}
catch { }
}
Example 3
You may want multiple handlers to have certian behaviour, for example logging their execution time. You could create a base class for (a subset of) your handlers:
public abstract class BaseHandler<THandler,TRequest, TResponse>
where THandler : notnull
where TRequest : notnull
{
protected readonly ILogger<THandler> _logger;
protected readonly IDbConnectionFactory _connectionFactory;
protected readonly IHostEnvironment _hostEnvironment;
public BaseHandler(IBaseHandlerServices baseHandlerServices)
{
_logger = baseHandlerServices.LoggerFactory.CreateLogger<THandler>();
_connectionFactory = baseHandlerServices.ConnectionFactory;
_hostEnvironment = baseHandlerServices.HostEnvironment;
}
public async Task<TResponse> HandleAsync(TRequest request, CancellationToken cancellationToken = default)
{
HandleBefore(request);
var result = await HandleCoreAsync(request, cancellationToken);
HandleAfter();
return result;
}
private void HandleBefore(TRequest request)
{
if (!_hostEnvironment.IsProduction())
{
_logger.LogInformation("Start handling request {RequestMembers}.", request.ToKeyValuePairsString());
}
StartTime = DateTime.UtcNow;
}
DateTime StartTime;
protected abstract Task<TResponse> HandleCoreAsync(
TRequest request,
CancellationToken cancellationToken);
private void HandleAfter()
{
var totalMilliseconds = (DateTime.UtcNow - StartTime).TotalMilliseconds;
if (!_hostEnvironment.IsProduction() || totalMilliseconds > 500)
{
_logger.LogInformation("Finished in {TotalMilliseconds}ms.", totalMilliseconds);
}
}
}
Inherit:
public class ProductOverviewQueryHandler
: BaseHandler<ProductOverviewQueryHandler, Query, Result>
{
public ProductOverviewQueryHandler(IBaseHandlerServices baseHandlerServices)
: base(baseHandlerServices)
{ }
protected override async Task<Result> HandleCoreAsync(
Query query,
CancellationToken cancellationToken)
{
await using var connection = await _connectionFactory.GetOpenConnectionAsync(cancellationToken);
// execute
return new Result
{
// set properties
};
}
}
Use:
var result = await i.Get<ProductOverviewQueryHandler>().HandleAsync(query);
Try it out
The examples above give an idea of how you can be creative with IGet. Share your own examples online to spread the word about IGet.
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 AddIGet()
extension method.
Product | Versions 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. |
-
.NETStandard 2.0
NuGet packages (1)
Showing the top 1 NuGet packages that depend on IGet:
Package | Downloads |
---|---|
IGet.GetAll
Extends IGet. Get an IEnumerable of class instances (with their dependencies injected) via i.GetAll<IMyInterface>() or i.GetAll<MyBaseClass>(). Additional setup: serviceCollection.AddIGetAll(new [] { typeof(Startup).Assembly, ... }). See the readme for many examples. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.1.8 | 17,873 | 12/13/2023 |
1.1.7 | 133 | 12/13/2023 |
1.1.6 | 5,161 | 4/12/2023 |
1.1.5 | 970 | 3/29/2023 |
1.1.4 | 297 | 3/21/2023 |
1.1.3 | 297 | 3/20/2023 |
1.1.2 | 190 | 3/19/2023 |
1.1.1 | 326 | 3/16/2023 |
1.1.0 | 200 | 3/15/2023 |
1.0.14 | 198 | 3/15/2023 |
1.0.13 | 209 | 3/14/2023 |
1.0.12 | 207 | 3/14/2023 |
1.0.11 | 212 | 3/14/2023 |
1.0.10 | 208 | 3/14/2023 |
1.0.9 | 212 | 3/13/2023 |
1.0.8 | 215 | 3/13/2023 |
1.0.7 | 205 | 3/13/2023 |
1.0.6 | 194 | 3/13/2023 |
1.0.5 | 207 | 3/12/2023 |
1.0.4 | 222 | 3/12/2023 |
1.0.3 | 197 | 3/11/2023 |
1.0.2 | 211 | 3/10/2023 |
1.0.1 | 227 | 3/10/2023 |
1.0.0 | 227 | 3/10/2023 |
1.0.0-alpha | 147 | 3/10/2023 |
v1.0.*: updates of the readme.
v1.1.0: add T Get<T>(Type type).
v1.1.*: updates of the readme.