Dustcloud.IoC.Universal 1.0.4

dotnet add package Dustcloud.IoC.Universal --version 1.0.4
NuGet\Install-Package Dustcloud.IoC.Universal -Version 1.0.4
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="Dustcloud.IoC.Universal" Version="1.0.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Dustcloud.IoC.Universal --version 1.0.4
#r "nuget: Dustcloud.IoC.Universal, 1.0.4"
#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 Dustcloud.IoC.Universal as a Cake Addin
#addin nuget:?package=Dustcloud.IoC.Universal&version=1.0.4

// Install Dustcloud.IoC.Universal as a Cake Tool
#tool nuget:?package=Dustcloud.IoC.Universal&version=1.0.4

Dustcloud IOC Universal

Introduction

This library is a wrapper that will allow you to register types in a DI container on a pick-and-choose basis, using a very simple attribute-like approach.

Usage

DependencyInitializer class

The main point of entry is the static DependencyInitializer class and its subsequent Initialize() method.
It registers all of the classes decorated with the DependencyConfigurationAttribute in your code.
It can only be run once, any subsequent calls to this method will result in a ResolverAlreadyInitializedException.

Please use this method from within your App.xaml.cs at the top of the "OnLaunched" method.

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
   var rootFrame = Window.Current.Content as Frame;
   var resolver = DependencyInitializer.Initialize();
   { ... }
   
}

If you decide to register any specific types yourself, please make sure you run the .BuildResolver() method of the IResolver.

	resolver.Register(typeof(ICoreAcceleratorKeys), instance: rootFrame.Dispatcher, manager: LifetimeManagerType.Singleton);
	resolver.Register(typeof(IMessenger), instance: Messenger.Default, manager: LifetimeManagerType.Singleton);
	resolver.BuildResolver();

To mark your class for registration, please decorate it with the DependencyConfigurationAttribute, as per

[DependencyConfiguration(typeof(*interface type*), typeof(*concrete type*), LifetimeManagerType.Transient/Scope/Singleton)]

e.g :

 [DependencyConfigurationAttribute(typeof(IWorkspaceService), typeof(WorkspaceService), LifetimeManagerType.Transient)]
 internal sealed class WorkspaceService : IWorkspaceService
 {
	public int Add(int x, int y)
	{
		return x + y;
	}
 }

 public interface IWorkspaceService
 {
	int Add(int x, int y);
 }

LifeTimeManagerType enum

The LifeTimeManagerType ensures that our class is instantiated the way we want, whereby:
Transient: Specifies, that when the type is injected/resolved, the instance will be freshly created every time.
Singleton: Specifies, that when the type is injected/resolved the instance will be a singleton, meaning it will always be the same instance.
Scoped: deprecated/not needed.

Accessing your registered objects:

To inject a part into your class, you can use the constructor of that class and create a class-scope variable of that same type to use in your class, as per:

[DependencyConfiguration(typeof(IStitcherService), typeof(StitcherService), LifetimeManagerType.Singleton)]
internal sealed class StitcherService : IStitcherService
{
    private readonly ILogger _logger;
    private readonly IMessengerService _messengerService;
	private readonly IResolver _resolver;

    public StitcherService(ILogger logger, 
                           IMessengerService messengerService,
                           IResolver resolver)
    {
        _logger = logger;
        _messengerService = messengerService;
		solver = resolver;
    }

	public void DoStuff()
    {
	    //..........
	    logger.Log(MessageType.Info, "My first injected service works!");
	}
}
Please note that you can inject the IResolver anywhere in your project, as it will always be registered first.
The above strategy works best with shared services (singletons).

For transient classes, you might want to make use of your IResolver interface injected into the service, like so:

public void DoStuff()
{
	var service = resolver.Resolve<IDirectoryService>();
	service.Initialize();
}

IPartCreationCompleted

Another cool functionality of this library, is the IPartCreationCompleted interface, which may be used to run code after the part (the class) gets created (i.e., after the constructor finished),
and before any and all events that may be fired after the creation of the part.
For example:

[DependencyConfiguration(typeof(IWorkspaceViewModel), typeof(WorkspaceViewModel), LifetimeManagerType.Singleton)]
internal sealed partial class WorkspaceViewModel : IWorkspaceViewModel, IPartCreationComplete
{
	public WorkspaceViewModel(IWorkspaceService workspaceService,	 
			IMessengerService messengerService,
			IResolver resolver,
			ILogger logger)
	{
		_workspaceService = workspaceService;
		_messengerService = messengerService;
		_logger = logger;
		_resolver = unityResolver;
	}
	 
	public void OnPartCreationCompleted()
	{
		CreateReportCommand = new RelayCommand(ExecuteCreateReport, CanExecuteCreateReport);
		FileCloseCommand = new RelayCommand(CleanUp);
	
		InitializeMessengerSubscriptions();
	}
}
The above exercise leaves the constructor clean and concise, while also allowing for barebones unit testing.

As per:

	private sealed class WorkspaceViewModelModelBuilder
    {
            private IWorkspaceService workspaceService;
            private IMessengerService messengerService;
            private IResolver resolver;
			private ILogger logger;
						
            internal WorkspaceViewModel Build(bool onPartCreated = true)
            {
                var vm = new WorkspaceViewModel(workspaceService ?? Mock.Of<IWorkspaceService>(),
                                                 messengerService ?? Mock.Of<IMessengerService>(),
                                                 unityResolver ?? Mock.Of<IUnityResolver>(),
                                                 logger ?? Mock.Of<ILogger>());

                if(onPartCreated)
                    vm.OnPartCreationCompleted();

                return vm;
            }
	}
	
	[Test]
	public void Test()
	{
	//inside a test method:
		 var vm = new WorkspaceViewModelBuilder().With(messengerServiceMock.Object)
												 .With(logger.Object)
												 .With(resolverMock.Object)
												 .Build(false);
	}
Product Compatible and additional computed target framework versions.
Universal Windows Platform uap was computed.  uap10.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.4 394 3/12/2021

First official release.