Abstractions for dependency injection.
Commonly Used Types:
EgonsoftHU.Extensions.DependencyInjection.IAssemblyRegistry
EgonsoftHU.Extensions.DependencyInjection.DefaultAssemblyRegistry
The motivation behind this project is to automatically discover and load all relevant assemblies into the current AppDomain
.
You can download the package from nuget.org.
You can find the release notes here.
First, install the EgonsoftHU.Extensions.DependencyInjection.Abstractions NuGet package.
dotnet add package EgonsoftHU.Extensions.DependencyInjection.Abstractions
Then, you may configure the logging of the DefaultAssemblyRegistry
class to use the logging library you configured in your project.
Please note:
- The internal dependency to
Serilog
has been removed from the package, hence no log event fromDefaultAssemblyRegistry
is logged by default. - It is optional to configure logging for
DefaultAssemblyRegistry
. - There are 2 forms of the message templates:
logEvent.MessageTemplate.Structured
for use with structured logging, e.g.Serilog
.logEvent.MessageTemplate.Indexed
for use withString.Format()
.
Example configuration for Serilog:
using EgonsoftHU.Extensions.DependencyInjection;
using EgonsoftHU.Extensions.Logging;
using Serilog;
ILogger logger = Log.Logger.ForContext<DefaultAssemblyRegistry>();
DefaultAssemblyRegistry.ConfigureLogging(
logEvent =>
logger
.ForContext(PropertyBagEnricher.Create().AddRange(logEvent.Properties))
.Verbose(logEvent.MessageTemplate.Structured, logEvent.Arguments)
);
Example configuration for Microsoft.Extensions.Logging:
using EgonsoftHU.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
ILoggerFactory loggerFactory = LoggerFactory.Create(
loggingBuilder =>
loggingBuilder
.SetMinimumLevel(LogLevel.Debug)
.AddJsonConsole(
options =>
{
options.IncludeScopes = true;
options.JsonWriterOptions = new() { Indented = true };
}
)
.AddDebug()
);
DefaultAssemblyRegistry.ConfigureLogging(
logEvent =>
{
ILogger logger = loggerFactory.CreateLogger<DefaultAssemblyRegistry>();
using (logger.BeginScope(logEvent.Properties))
{
logger.LogDebug(logEvent.MessageTemplate.Structured, logEvent.Arguments);
}
},
LoggingLibrary.MicrosoftExtensionsLogging
);
Example configuration for System.Console:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EgonsoftHU.Extensions.DependencyInjection;
DefaultAssemblyRegistry.ConfigureLogging(
logEvent =>
{
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendFormat(logEvent.MessageTemplate.Indexed, logEvent.Arguments);
sb.AppendLine();
int maxKeyLength = logEvent.Properties.Keys.Max(key => key.Length);
foreach (KeyValuePair<string, object?> property in logEvent.Properties)
{
sb.AppendFormat(
" [{0}] = [{1}]",
property.Key.PadRight(maxKeyLength),
property.Value
);
sb.AppendLine();
}
Console.WriteLine(sb);
}
);
Then, you can initialize an instance of the DefaultAssemblyRegistry
class by providing the file name prefixes of your assemblies.
using EgonsoftHU.Extensions.DependencyInjection;
// This will search for assemblies as below then loads them into the current AppDomain:
// Root Folder : AppContext.BaseDirectory
// Pattern #1 : YourCompany.*.dll
// Pattern #2 : Custom.*.dll
// SearchOption: SearchOption.AllDirectories
DefaultAssemblyRegistry.Initialize("YourCompany", "Custom");
Finally, if you need the loaded assemblies then get the current instance of the DefaultAssemblyRegistry
class.
using EgonsoftHU.Extensions.DependencyInjection;
var assemblies = DefaultAssemblyRegistry.Current.GetAssemblies();
Suppose you have an ASP.NET Core project that needs to load controllers from other projects.
Let's create an extension method that will do the magic.
using System.Reflection;
using EgonsoftHU.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
public static class MvcBuilderExtensions
{
public static IMvcBuilder AddApplicationParts(this IMvcBuilder builder)
{
// This is the assembly of your ASP.NET Core startup project.
// We will not call the AddApplicationPart() method for this assembly.
Assembly entryAssembly = Assembly.GetEntryAssembly();
DefaultAssemblyRegistry
.Current
.GetAssemblies()
.Where(
assembly =>
assembly != entryAssembly
&&
assembly.DefinedTypes.Any(typeInfo => typeof(ControllerBase).IsAssignableFrom(typeInfo))
)
.ToList()
.ForEach(assembly => builder.AddApplicationPart(assembly));
return builder;
}
}
Now you can use it in your Startup.cs
file.
using EgonsoftHU.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
public void ConfigureServices(IServiceCollection services)
{
// Let's initialize the assembly registry.
DefaultAssemblyRegistry.Initialize("YourCompany", "Custom");
services
.AddMvc()
.AddApplicationParts(); // <-- This will load controllers, view components, or tag helpers from all assemblies other than the entry assembly.
}