A utility library that scan and bind your classes automatically to IOC based on Attribute and also can bind strong type data as IOptions from configuration.
Add a reference of latest nuget package of Bolt.IocScanner. In your Startup class add following lines
builder.Services.Scan<Startup>();
// Or if you want to bind options from configuration pas configuration
builser.Services.Scan<Startup>(builder.Configuration)
Now all classes in the same assembly of Startup class will be scanned and automatically bind to servicecollection. For example you create a new class in same project as below:
public interface IBooksProxy
{
Task<Book> Get(string id);
}
[AutoBind]
public class BooksProxy : IBooksProxy
{
public Task<Book> Get(string id)
{
// your implementation here
}
}
You don't need to open the startup class and add code to register this proxy class to servicecollection. you can readily use this class in your controller or any other dependent classes. For example
public class BooksController : Controller
{
private readonly IBooksProxy _proxy;
public BooksController(IBooksProxy proxy)
{
_proxy = proxy;
}
}
Yes you can. Here is an example:
builder.Services.Scan(new []{
typeof(BookStore.Web.Startup).Assembly,
typeof(BookStore.Infrastructure.ISerializer).Assembly
}, build.Configuration);
Just add AutoBind attribute to that class. When a class doesn't have any interface then it bind to self:
[AutoBind]
public class BooksProxy
{
public Task<Book> Get(string id)
{
// your code here ...
}
}
public class BooksController : Controller
{
private readonly BooksProxy _proxy;
public BooksController(BooksProxy proxy)
{
_proxy = proxy;
}
}
Yes you can. Here is an example where all classes matches the criteria
will bind automatically without the need to add AutoBind attribute.
builder.Services.Scan<Startup>(new IocScannerOptions
{
BindServicesOnMatch = (type) => ["Provider","Service"].Any(x => type.Name.EndsWith(x))
});By default all bindings use transient lifecycle. If you want different lifecycle then you need decorate your class with an attribute as below and can mention what lifecycle you like the class to bind.
[AutoBind(LifeCycle.Scoped)]
public class BooksProxy
{
}
// or if you like to register as singleton
[AutoBind(LifeCycle.Singleton)]
public class ConnectionPool
{
}
Theres four ways you can do this.
[SkipAutoBind]
public class ThisClassNotBind
{
}
// By default we exclude IDispoable interface
services.Scan<Startup>(new IocScannerOptions
{
InterfacesToExclude = new[] { typeof(ThisClassNotBind) }
});
you can tell in option that only bind when an "AutoBind" attribute provided. In that case any class in assemblies doesn't have "AutoBind" attribute will not be registered in ioc.
public void ConfigureServices(IServiceCollection services)
{
services.Scan<Startup>(new IocScannerOptions
{
SkipWhenAutoBindMissing = true
});
}
public void ConfigureServices(IServiceCollection services)
{
services.Scan<Startup>(new IocScannerOptions()
.Exclude(t => t.Name.Equals("Startup")));
}
Yes if a class implement more than one interfaces the lib bind the class against all interfaces. In case of Singleton and Scoped lifecycle all interface bind against same instance unless
any interface provided in InterfacesToExclude property of IocScannerOptions. For example:
[AutoBind(LifeCycle.Singleton)]
public class Implementation : IProvideName, IProvidePrice
{
}
Now if you request for IProvideName and IProvidePrice both case the service provider will return same instance of Implementation throughout the whole life of the application.
Same applies for Scoped lifecycle but in that case the behaviour is true for same scope. For new scope a new instance of Implementation will be provided by service provider.
The library scan for IServiceRegistry interface and execute them to allow you to bind by yourself.
public class SampleRegistration : IServiceRegistry
{
public void Register(IServiceCollection serviceCollection)
{
serviceCollection.Bind(typeof(IDataProvider<,>),typeof(DefaultDataProvider<,>));
}
}
Define you settings DTO and decorate with attribute BindFromConfig
[BindFromConfig]
public class TenantSettings
{
public string Theme {get; set; }
} Now make sure you define the settings in appsettings.config or your configuration providers.
{
"App": {
"TenantSettings": {
"Theme": "dark"
}
}
} You should able to use this settings as below:
public class ColorPicker(IOptions<TenantSettings> options)
{
public string TextColor()
{
if(options.Value.Theme == "dark") return "white";
return "black";
}
}Yes you can. See example below:
[BindFromConfig("Bolt:Tenants:Settings", isOptional: false)]
public class TenantSettings
{
public string Theme {get; set; }
} Now the system will load the settings from defined section name in attribute.
{
"Bolt": {
"Tenants": {
"Settings": {
"Theme": "dark"
}
}
}
} Yes you can. Just pass isOptional to true as below:
[BindFromConfig("Bolt:Tenants:Settings", isOptional: true)]
public class TenantSettings
{
public string Theme {get; set; }
}