Resolver 1.0.4
dotnet add package Resolver --version 1.0.4
NuGet\Install-Package Resolver -Version 1.0.4
<PackageReference Include="Resolver" Version="1.0.4" />
<PackageVersion Include="Resolver" Version="1.0.4" />
<PackageReference Include="Resolver" />
paket add Resolver --version 1.0.4
#r "nuget: Resolver, 1.0.4"
#:package Resolver@1.0.4
#addin nuget:?package=Resolver&version=1.0.4
#tool nuget:?package=Resolver&version=1.0.4
Resolver
Resolver helps you write loosely coupled code that is easy to change, compose and test. The library is easy to adopt, works with .NET Standard and exposes a concise syntax.
Read more about Dependency Injection.
Get Started
Available on NuGet: Resolver
NuGet Package Manager: Install-Package Resolver
Contents
Resolver
Can register a new dependency, build new objects and resolve their dependencies.Resolvable
Attribute to be used on properties that will automatically be resolved.
Usage
Resolver is intended to be used as an singleton. However, that decision belongs to the consumer.
var resolver = new Resolver();
Register
Once you build you a Resolver, you can use it to register dependencies:
ISoundService soundService = new SoundService();
resolver.Register(soundService);
Resolve
After you register a property, you can resolve objects that contain properties of the same type as the registered dependencies.
class PageViewModel
{
public ISoundService Sound { get; set; }
}
var viewModel = resolver.Resolve<PageViewModel>();
At this point, Sound
property of the viewModel
object has been populated with soundService
object.
Notice: Resolve
only creates new objects, but no new dependencies.
E.g.:
var viewModel1 = resolver.Resolve<PageViewModel>();
var viewModel2 = resolver.Resolve<PageViewModel>();
viewModel1.Sound
is equal to viewModel2.Sound
by pointing to the same reference soundService
.
[Resolvable]
Resolvable
attribute can be use on any property that will have to be instantiated at runtime.
class ControlViewModel
{
}
class NavigationViewModel
{
[Resolvable]
public ControlViewModel Control { get; set; }
}
var navigation = resolver.Resolve<NavigationViewModel>();
At this point navigation.Control
has been instantiated and can therefore be used.
Registered dependencies vs. [Resolvable]
properties
As you have seen above, the main difference between a registered dependency and a [Resolvable]
property is their lifetime and their relation to their owner.
Registered dependencies have a longer lifetime than the objects that consume them. E.g.: a SoundService can outlive different app pages.
[Resolvable]
properties are have a shorter or equal lifetime than their owner's. E.g.: a property CreateAccountView only makes sense on a Start page, therefore there is no need to keep it around longer that the Start page.
Finally, registered dependencies and [Resolvable]
can be used in the same class, and the Resolve
method with figure out how to handle each according to the rules mentioned above. Furthermore, the newly instantiated [Resolvable]
property follows the same Resolve
logic, meaning that any further dependencies it has will be resolved as well (either registered or [Resolvable]
)
class ControlViewModel
{
public ISoundService Sound { get; set; }
}
class NavigationViewModel
{
[Resolvable]
public ControlViewModel Control { get; set; }
public ISoundService Sound { get; set; }
}
var navigation = resolver.Resolve<NavigationViewModel>();
At this point navigation.Control
has been instantiated, and both navigation.Sound
and navigation.Control.Sound
point to the same reference, soundService
.
Performance
Resolver
uses Reflection to inspect types and create objects. While Reflection is a powerful library, it does come with some performance penalty.
There are numerous resources where you can find more details about how fast Refection build objects, and Resolver's performance will follow Reflection's performance.
Here are tests performed on a DEBUG build that create 10.000 objects using instantiation and Resolve
.
- Scenario 1: No registered or
[Resolvable]
properties
Instantiate 10.000 objects | Resolve 10.000 objects |
---|---|
< 1 ms | 20 ms |
- Scenario 2: registered dependencies
Instantiate 10.000 objects | Resolve 10.000 objects |
|
---|---|---|
1 dependency | < 1 ms | 5 ms |
10 dependencies | 4 ms | 175 ms |
- Scenario 3:
[Resolvable]
properties
Instantiate 10.000 objects | Resolve 10.000 objects |
|
---|---|---|
1 dependency | < 1 ms | 50 ms |
10 dependencies | 4 ms | 400 ms |
The performance penalty is noticeable when creating a large number of objects, especially when using [Resolvable]
properties.
That is because Reflection needs to assign and / or instantiate (number of objects) * (number of dependencies)
.
In real world scenarios, general purpose apps tend to have smaller object hierarchies making the use of DI acceptable. In most cases even objects with a complex hierarchy or multiple levels of child objects can be resolved in less than 1 ms.
While analyzing CPU performance in real world app usage the cumulative CPU time spend by Resolver accounts for less than 1% of the total time spend on high activity scenarios that require creating new objects.
Why use Resolver
Several other platforms implement Dependency Injection for .NET. Some of the most popular ones include: Ninject, Castle Windsor.
Resolver
is meant to be simple and easy to understand.
The Resolver
class contains less than 160 lines of code.
GetNewObject
and ResolveObjectProperties
, the code methods of the framework represent less than half the implementation of the Resolver
class.
The conciseness of the implementation makes it a good candidate for consumers looking for either a lightweight or an easy to understand DI implementation.
Apps using Resolver
I built Resolver
out of necessity, after passing dependencies via constructors got out of hand and after I learned about Dependency Injection.
It has since simplified my code, allowed me to focus on the actual logic instead of infrastructure code and ultimately helped me ship faster and better apps.
I used Resolver
in several of my games published in Microsoft Store, check them out at http://frenzygames.net
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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.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
- 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.