Cofoundry relies heavily on dependency injection, building on top of the .NET Core dependency abtractions to provide additional features such as:
- Automatic registrations
- Modular dependency registrations
- Overriding existing implementations
These features are essential for Cofoundry's modular framework to work, and you may find benefit in using them structure your code, however, for most scenarios you can continue to use the .NET Core dependency framework if you prefer.
Automatic Registrations
Most Cofoundry services will automatically register themselves with the DI container, so you won't need to worry about registering types such as:
- Command & Query Handlers
- Custom Entity Definitions
- Background Tasks
- Startup Tasks
- User Areas
- Permissions
- "Registration" implementations (e.g. IRouteRegistration & IStartupTask)
- Plus many more
In fact, for some applications you may not need to worry about dependencies at all.
Modular Registrations
Cofoundry provides an abstraction for registering dependencies that it uses internally, but you can use it too if you want to take advantage of a standardized approach to modular registrations. This is also essential for allowing plugin developers to register types and override base level implementations.
To register a type, all you need to do is create a class that implements IDependencyRegistration
and add your registrations in the Register
method. Your types will automatically be registered at startup. You can implement as many of these registration classes as you like which can be handy for keeping your registrations and code modular.
using Cofoundry.Core.DependencyInjection;
public class ExampleRegistration : IDependencyRegistration
{
public void Register(IContainerRegister container)
{
container
.Register<IMyService, MyService>()
.RegisterSingleton<ExampleHelper>()
.RegisterAll<IExampleTask>()
.RegisterGeneric(typeof(IRepository<>), typeof(Repository<>));
}
}
Overriding Registrations
Most registration methods have an optional RegistrationOptions
parameter which allows you to override an existing implementation. This is useful (particularly for plugin authors) if you want to override the base Cofoundry implementation with your own version.
using Cofoundry.Core.DependencyInjection;
public class ExampleOverrideRegistration : IDependencyRegistration
{
public void Register(IContainerRegister container)
{
var registrationOptions = new RegistrationOptions() { ReplaceExisting = true };
container.Register<IMyService, MyService>(registrationOptions);
// OR use the static helper
container.Register<IMyService, MyService>(RegistrationOptions.Override());
}
}
RegistrationOptions
has an additional priority property, but this should not normally be needed and should only be used as a last resort. The property is an integer but the RegistrationOverridePriority
enum is best used for predictable results:
- RegistrationOverridePriority.Low: Will override the default implementation and nothing more. Typically used inside the Cofoundry framework to override a default/empty implementation lower down in the framework.
- RegistrationOverridePriority.Normal: Default and the option to typically use in a plugin. Will override the existing implementation and any low level (typically default/placeholder) implementation.
- RegistrationOverridePriority.High: A higher level priority that should rarely be used (and never in the framework or plugins), but may be needed in a client application to override a plugin.
Registering Dependencies in other assemblies
Cofoundry uses a rule based system to determine which assemblies to scan for dependencies on startup. To keep the startup process lean, the default ruleset scans assemblies with names that match one the following criteria:
- Contains the text "Cofoundry", e.g.
Cofoundry.Core
orMyApp.CofoundryModule
- Starts with the entry assembly name (typically your web app project name) e.g.
MyApp
orMyApp.Domain
- Contains the text "Plugin", but not at the start, e.g.
Cofoundry.Plugins.Azure
orMyApp.MyPlugin
Custom Discovery Rules
You can implement your own discovery rules by implementing IAssemblyDiscoveryRule
and registering it with Cofoundry during application startup:
MyAssemblyDiscoveryRule.cs
using Cofoundry.Web;
using Microsoft.Extensions.DependencyModel;
public class MyAssemblyDiscoveryRule : IAssemblyDiscoveryRule
{
public bool CanInclude(
RuntimeLibrary libraryToCheck,
IAssemblyDiscoveryRuleContext context
)
{
return libraryToCheck.Name.StartsWith("MyNamespace.");
}
}
Program.cs
// other code removed
builder
.Services
.AddMvc()
.AddCofoundry(builder.Configuration, c =>
{
c.AssemblyDiscoveryRules.Add(new MyAssemblyDiscoveryRule());
});