Getting module name or identification - c#

For my application I'm trying to write a configuration controller, to load and save settings for certain modules. To do this I am going to use an INI file, where the section names would represent the module names (or other identification), and the values represented by a key.
I registered my controller in the bootstrapper, and use the interface in my constructor for injection in the appropriate classes. However I do not want to enter the module name every time I need to get or set a value, so I tried to use Caller info to find out what module (or class) is calling the method, but this apparently does not work (return empty string).
Is there another way to achieve what I'm trying to do?
Bootstrapper:
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterType<IConfig, ConfigController>(new ContainerControlledLifetimeManager());
}
Config interface:
public interface IConfig
{
string[] GetSettings(string caller = "");
void Set<T>(string setting, T value, string caller = "") where T : class;
T Get<T>(string setting, string caller = "") where T : class;
}

The use of caller argument is error prone. You have many options to avoid it:
Register a ConfigController for each module. Unity supports multiple named registration. You can inject the right controller in each module in the module initialization, or with a Dependency attribute:
Container.Register<IConfig, ConfigController>("module1",
new InjectionConstructor("module1"))
.Register<IConfig, ConfigController>("module2",
new InjectionConstructor("module2"));
class Module1 {
public Module1([Dependency("module1")] IConfig config) {... }
}
Define and implement a IConfigFactory that returns a configured IConfig implementation.
interface IConfigFactory {
IConfig Create(String moduleName);
}
The ConfigController could identify the module detecting the method the made the call.

Related

Options pattern: Two option objects, one needs information from the other

I'm using the Options pattern to configure my ASP.net Core 3.1 web app.
There are two options classes:
public class SystemOptions
{
public string RootPath { get; set; }
}
public class ModuleOptions
{
public string SubPath { get; set; }
// this should become something like RootPath + SubPath
public string FullPath { get; }
}
And the associated appsettings.json
{
"SystemOptions": {
"RootPath": "\\webdav"
},
"ModuleOptions": {
"SubPath": "\subdirformodule"
}
}
And in Startup:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SystemOptions>(configuration.GetSection("SystemOptions"));
services.Configure<ModuleOptions>(configuration.GetSection("ModuleOptions"));
}
Now I would like to initialize the FullPath in ModuleOptions once during app startup.
Therefore I need access to the SystemOptions.RootPath from within the ModuleOptions.
Is this possible?
I tried the following:
I added an InitializeFullPath() method to the ModuleOptions:
public string InitializeFullPath(string basePath)
{
// concat basePath and SubPath and return
... return fullPath;
}
and tried to use this in ConfigureServices:
services.Configure<SystemOptions>(configuration.GetSection("SystemOptions"));
services.AddOptions<ModuleOptions>()
.Configure<SystemOptions>((s, m) => m.FullPath = m.InitializeFullPath(s.RootPath));
But all I get is:
"No service for type '...SystemOptions' has been registered."
later on when Startup.Configure() is executed.
(And by the time this error occured, the InitializeFullPath method has not been executed at all - a breakpoint set there was not hit.)
So I have two questions:
how can I use the content of one option object during initialization of the second option object?
When will the delegate that you can specify in Configure() be executed?
I am going to answer your second question first. The configuration delegate is invoked the first time the Value property of the IOptions<YourOptions> is invoked. This interface is registered as a singleton so it's a one-time only thing. For IOptionsMonitor/IOptionsSnapshot they are similarly invoked on every new instance of the options.
Now to your first question... You were close! This should work:
services.AddOptions<ModuleOptions>()
.Configure<IOptions<SystemOptions>>(
(mod, sys) => mod.FullPath = mod.InitializeFullPath(sys.Value.RootPath)
);
Note that we are using IOptions<SystemOptions> and .Value. The Configure method that is chained to AddOptions is not the same as the one directly on the service collection; the generic arguments are the dependent service types and the first parameter is the options type from AddOptions. So that means that you reversed the arguments to the delegate (the option being configured is the first parameter).
Another...option is to use the IConfigureOptions interface. I typically go this route and don't use the form you have shown, even for "simple" dependent configuration:
public ModuleOptionsConfigurator : IConfigureOptions<ModuleOptions>
{
private readonly SystemOptions _sys;
public ModuleOptionsConfigurator(IOptions<SystemOptions> opts)
=> _sys = opts.Value;
public void Configure(ModuleOptions mod)
{
mod.FullPath = mod.InitializeFullPath(_sys.RootPath);
}
}
Which you then register with DI like so:
services.Configure<SystemOptions>(configuration.GetSection("SystemOptions"));
services.Configure<ModuleOptions>(configuration.GetSection("ModuleOptions"))
// register the configurator
services.ConfigureOptions<ModuleOptionsConfigurator>();
This allows you to encapsulate any sort of configurarion logic into a class. You can take zero dependencies up to however many you need.
The IPostConfigureOptions<> interface works similarly, but will run after all other Configure callbacks and IConfigureOptions<> implementations (and allows you to act differently for named options). Based on your description, this may be the better interface:
public ModuleOptionsPostConfigurator : IPostConfigureOptions<ModuleOptions>
{
private readonly SystemOptions _sys;
public ModuleOptionsPostConfigurator(IOptions<SystemOptions> opts)
=> _sys = opts.Value;
public void PostConfigure(string name, ModuleOptions mod)
{
mod.FullPath = mod.InitializeFullPath(_sys.RootPath);
}
}
IPostConfigureOptions is registered the same way as IConfigureOptions:
// register the configurator
services.ConfigureOptions<ModuleOptionsPostConfigurator>();
You can also combine the two interfaces in one implementing class, which I have often found a case for.
See the official documentation for more information on the options patterns.

How to override config.json data using C# code?

I have followed this blog here on how to use IOC with Autofac, this is the first time hearing about IOC and autoFac.
I have downloaded the project from the link the blog provided and I have been looking through the project and I am trying to find out how the classes:
public class DatabaseSettings
{
public string ConnectionString { get; protected set; }
public int TimeoutSeconds { get; protected set; }
}
public class UserSettings
{
public string DefaultUsername { get; protected set; }
public bool ActiveByDefault { get; protected set; }
}
... gets populated without no invocation of the load function in 'Database reader'?
Is it because of (these) :
public T Load<T>() where T : class, new() => Load(typeof(T)) as T;
public T LoadSection<T>() where T : class, new() => LoadSection(typeof(T)) as T;
If it is the above codes what are they(so I can read up on how they work)?
Final Question, Is it possible to save the data back to the config.json using this approach?
The entries like
public T Load<T>() where T : class, new() => Load(typeof(T)) as T;
just mean you can use the "generic" syntax when accessing in the functions. It's a bit neater than passing in the Type as a method parameter, and also means you get a strongly-typed object back. Another way of writing the above is:
public T Load<T>() where T : class, new()
{
var type = typeof(T);
var loaded = Load(type);
return loaded as T;
}
It's a useful language feature but nothing to do with IoC itself. The IoC magic itself is mostly contained in SettingsModule. This bit:
builder.RegisterInstance(new SettingsReader(_configurationFilePath, _sectionNameSuffix))
.As<ISettingsReader>()
.SingleInstance();
tells Autofac to provide a SettingsReader (the RegisterInstance part) whenever anyone requests an ISettingsReader (the As<> bit). .SingleInstance means it will treat the SettingsReader as a singleton: only one of them will be created and that same object is passed to everywhere an ISettingsReader is requested.
This other part
var settings = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.Name.EndsWith(_sectionNameSuffix, StringComparison.InvariantCulture))
.ToList();
settings.ForEach(type =>
{
builder.Register(c => c.Resolve<ISettingsReader>().LoadSection(type))
.As(type)
.SingleInstance();
});
is just a fancy way of automatically telling it what to do whenever it sees a request for DatabaseSettings or UserSettings. As per the original question, this is where the Load function is actually called. A simpler way of doing the same would just be:
builder.Register(c => c.Resolve<ISettingsReader>().LoadSection(typeof(DatabaseSettings))).As<DatabaseSettings>();
builder.Register(c => c.Resolve<ISettingsReader>().LoadSection(typeof(UserSettings))).As<UserSettings>();
You could write out the logic for those as "when a DatabaseSettings object is requested (.As), find an implementation for ISettingsReader, and then call LoadSection on that (the first part)"
Elsewhere in the Container class there's also this:
builder.RegisterType<UserService>().As<IUserService>();
which just tells Autofac what to do for an IUserService.
The result is that where in the main application method we have:
using (var scope = container.BeginLifetimeScope())
{
var userService = scope.Resolve<IUserService>();
Without that main method "knowing" anything about the concrete types it uses, we'll get a fully functioning IUserService back. Internally, Autofac will resolve the chain of dependencies required by plugging all of the constructor parameters for each type in the chain. That might look something like:
IUserService requested
Resolve UserService
Resolve IDatabase
return Database
Resolve UserSettings
Resolve ISettingsReader
return SettingsReader
Call LoadSection on ISettingsReader
return generated UserSettings object
For your Final Question - yes! However, IoC isn't necessarily what would enable you to do so. It just lets you bind together and access whichever custom classes you'd create to allow saving.
You might create a new interface like
public interface ISettingsWriter
{
void Save<T>(T settings);
}
And then for some reason you add a method which accesses that in the UserService:
public class UserService : IUserService
{
private readonly IDatabase _database;
private readonly UserSettings _userSettings;
private readonly ISettingsWriter _settingsWriter;
public UserService(IDatabase database, UserSettings userSettings, ISettingsWriter settingsWriter)
{
_database = database;
_userSettings = userSettings;
_settingsWriter = settingsWriter;
}
public void UpdateUserSettings()
{
_settingsWriter.Save(new UserSettings());
}
Using it in this way is a bit simpler than in the original sample code - I'd recommend taking this approach until you get more used to it. It means that the only other thing you'd need to add would be the registration for the settings writer, like:
builder.RegisterType<SettingsWriter>()
.As<ISettingsWriter>();

Bootstrapping an ASP.NET Core 2.1 application containing multiple module types using DI

Started building the infrastructure for a multi-tenant ASP.NET Core 2.1 application which is and will be composed of many modules.
The idea is to enable any modules which are to be added in the future, to be just plugged into the system, registering their own required dependencies on app startup and using the already registered dependencies (dependencies registered by other modules) if needed.
Let's first take a look at the sample code of how I imagined this would look like - from the top of my head.
Let's say we've got some kind of a module manager which we're gonna name just that - ModuleManager.
public class ModuleManager
{
// Let's store all of our module types here
private List<Type> moduleTypes;
void RegisterModules(Type webHostModuleType, IServiceCollection services)
{
// Find all module dependencies recursively
// (i.e. all modules that are specified in some, let's say 'DependsOn' attribute
// which decorates webHostModuleType)
moduleTypes = FindDependencies();
// Now we need to register all dependencies
foreach (Type moduleType in moduleTypes)
{
services.AddSingleton(moduleType);
}
// ... and we shouldn't forget to register the webHostModuleType too
services.AddSingleton(webHostModuleType);
}
}
Let's stop there for now and first define the module type. I think it is expected to presume that each module type can have different properties and fields based on their needs, but we will have to make all of them derive from a base module type. Let's call it BaseModule and this is how I imagined it to be:
public abstract class BaseModule
{
// I've currently got no idea on how this method should be defined
// Because it's supposed to register the concrete module's dependencies
// after the module has been instantiated... is that even possible?
// Should it be some kind of a factory method rather than void
// and serve as a lazy initializer? Is that also even possible?
// Something that should make use of IOptions<>?
public virtual void Init()
{
}
// Maybe some post-init code will be needed too
public virtual void PostInit()
{
}
}
And then we will have some concrete module types defined like this:
public class CoreModule : BaseModule
{
// some dependencies that need to be injected...
private readonly IHostingEnvironment hostingEnvironment;
private readonly IDontKnowSomeOtherDependency someOtherDependency;
public CoreModule(IHostingEnvironment hostingEnvironment, IDontKnowSomeOtherDependency someOtherDependency)
{
this.hostingEnvironment = hostingEnvironment;
this.someOtherDependency = someOtherDependency;
}
public override void Init()
{
// Somehow register additional services defined by this module,
// after it's been instantiated
}
}
And let's say, for the completeness sake, our webHostModuleType is defined like this:
[DependsOn(typeof(CoreModule))]
public class WebHostModule : BaseModule
{
private readonly ISomeDependencyRegisteredInCoreModule someDependency;
public WebHostModule(ISomeDependencyRegisteredInCoreModule someDependency)
{
this.someDependency = someDependency;
}
public override void Init()
{
// Register some other service based on something from 'someDependency' field
}
}
And finally, let's go back to the module manager. Now it should have another method, executed after RegisterModules, which should instantiate each module in the correct order and then call Init() and PostInit() in the correct order, starting with the CoreModule and ending with WebHostModule. Something akin to this:
public void(?) LoadModules()
{
// Sort our modules first so dependencies come in first and webHostModuleType the last
SortEm(moduleTypes);
// Now we need to instantiate them.
// Can't do it manually as all of them might have different constructors
// So need to do it using our service collection
IServiceProvider serviceProvider = serviceCollection.BuildServicePRovider();
foreach (Type moduleType in moduleTypes)
{
BaseModule moduleInstance = serviceProvider.GetRequiredService(moduleType) as BaseModule;
// This is where we can register everything needed by the module instance.
// But can we?
moduleInstance.Init();
moduleInstance.PostInit();
}
// Maybe return the IServiceProvider instance we've built
// so we can return in to the `ConfigureServices` and return to ASP.NET Core from there?
}
As you can see, this approach raises many questions. Am I going in the right direction at all? Is there a way to register services from withing modules' Init() and PostInit() methods correctly?
If I call BuildServiceProvider() and then instantiate singleton instances, I would have to return that IServiceProvider instance back to ConfigureServices() so ASP.NET Core can use it. If I don't, it will build a new one and then all these singletons will be instantiated again.
But if I call ConfigureServices() then I won't be able to add new services, which I have to do after modules have been instantiated. What is the approach, if it's possible at all? Any opinions, ideas?
Wow such wall of text, thanks for reading at all!
Well, just one more opinion, but we are using the same standard ad the Net Core team, creating extension methods, so we just need to add the services were they are required:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddVtaeCommonServices();
services.AddMyServiceMX(Configuration);
services.AddOtherService(Configuration);
return VtaeConfig.ConfigVtae(services);
}
}
With this extension methods for example:
public static class CommonServicesExtension
{
public static IServiceCollection AddVtaeCommonServices(this IServiceCollection services)
{
services.AddNodaDateTime();
services.AddMemoryCache();
services.AddScoped<AuthorizedIpFilter>();
services.AddScoped<HttpContextManager>();
services.AddTransient<ProspectService>();
services.AddTransient<TokenService>();
services.AddTransient<TokenGenerator>();
services.AddTransient<ProspectsRepository>();
services.AddSingleton<UniqueIDGenerator>();
services.AddSingleton<SchedulerService>();
services.AddSingleton<ChecksumService>();
return services;
}
}
This way we can extract our functions to nuget packages and then simply re utilize them by adding the AddXXXService() in our startup

Best practice for Ninject to get different implementations based on top level project

I am just starting to learn Dependency Injection and I am stuck here.
My project has a WCF DataService over an Entity Framework DbContext.
public class MyDataService : DataService<MyDbContext>
{
protected override MyDbContext CreateDataSource()
{
// I want to use dependency injection for this
return new MyDbContext();
}
}
The class is either
a) IIS hosted, so I don't have any control
b) for integration tests, created with var host = new DataServiceHost(type, new Uri[] { });
both use different contstructors for MyDbContext
So basically to inject the Context with this
protected override MyDbContext CreateDataSource()
{
INinjectModule module = ???; // -
IKernel kernel = new StandardKernel(module);
return kernel.Get<MyDbContext>();
}
So the question is, what is best practice in this situation?
Should I:
a) Create a Module in a Class Library that both main projects and the service use
b) Create a public static Variable inside the DataService project that holds the Ninject module.
c) Create a public static Variable inside the DataService project that holds the Ninject kernel
d) Something else.
I would prefer something like
protected override MyDbContext CreateDataSource()
{
DefaultKernel.Get<MyDbContext>();
}
Firstly, you should have a Composition Root. That is, a single place where your Kernel is created (not in every single function).
Secondly, you don't need a NinjectModule here.. you're asking Ninject to create an instance of a concrete object (which in almost all circumstances.. defeats the purpose).
What you should create, is a separate NinjectModule pass it into the constructor of the Kernel.. something like this:
interface IContext {
}
class MyDbContext : DbContext, IContext {
}
class YourModule : NinjectModule {
protected override void Bind() {
Bind<IContext>().To<MyDbContext>();
}
}
// In your composition root somewhere
var kernel = new StandardKernel(new NinjectModule[] { new YourModule() });
// in your createdatasource method
kernel.Get<IContext>();
This will get you started. Normally, your composition root is what drives injection of objects throughout your application, thereby eliminating the need to pass the Kernel around (which you will have to do in your current setup).
The hard thing to understand when starting out with DI/IoC is that it is the container's job to create your entire dependency graph. Therefore, if you setup the following bindings:
IContract1 -> ConcreteObject1
IContract2 -> ConcreteObject2
IContract3 -> ConcreteObject3
..and have the following setup:
class ConcreteObject1 : IContract1 {
public ConcreteObject1(IContract2 contract3) {
}
}
class ConcreteObject2 : IContract2 {
public ConcreteObject2(IContract3 contract3) {
}
}
If you ask your container for a concrete implementation of IContract1 (which will be ConcreteObject1), then it will create it.... BUT: ConcreteObject1 requires a concrete implementation of IContract2 in the constructor. So the container says "Wait, I know how to create this".. and passes in an instance of ConcreteObject2. Again, it says "wait, ConcreteObject2 wants a concrete implementation of IContract3.. again, it goes and fetches one.
Hopefully that helps.

Database injection into a validation attribute with ASP MVC and Castle Windsor

I need some help - I am trying to use a custom validation attribute in an ASP.NET MVC web project that needs to make a database call.
I have windsor successfully working for the controllers and the IRepository interface is injected normally. The problem arrises when I need to inject the repository into the attribute class.
The attribute class has the following code:
public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
private readonly string message;
private readonly IArticleRepository articleRepository;
public ValidateUniqueUrlNodeAttribute(string message)
{
this.message = message;
}
public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
{
this.articleRepository = articleRepository;
}
public override IValidator Build()
{
var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };
ConfigureValidatorMessage(validator);
return validator;
}
My problem is that I cannot seem to make Windsor intercept the contruction of the attribute to pass in the IArticleRepository
The current code in my global.asax file is as follows:
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
container
.RegisterControllers(Assembly.GetExecutingAssembly())
.AddComponent<IArticleRepository, ArticleRepository>()
.AddComponent<ValidateUniqueUrlNodeAttribute>();
Any help would be greatly appreciated.
AFAIK no dependency injection container can directly manage an attribute, since it's instantiated by the runtime and there's no way to intercept that.
However, they can cheat by either:
Using a static gateway to the container (example), or
Using a "BuildUp" feature that injects whatever dependencies are found within an already-constructed object. This is called BuildUp in Unity or InjectProperties in Autofac.
Windsor doesn't support #2 (ref1, ref2), so you can either:
Try one of the hacks to make Windsor support #2 (hack1, hack2)
Use a static gateway
Implement your own IValidatorBuilder and make it use Windsor to create validators. I'm sure this is implemented somewhere but I can't find it right now...
Don't know if this helps, but I subclassed ValidationAttribute to expose a Resolve<T>() method like so:
public abstract class IocValidationAttribute : ValidationAttribute
{
protected T Resolve<T>()
{
return IocHelper.Container().Resolve<T>();
}
}
Then it can be used in any custom ValidatorAttribute that needs to hit a database:
public class UniqueEmailAttribute : IocValidationAttribute
{
public override bool IsValid(object value)
{
ICustomerRepository customerRepository = Resolve<ICustomerRepository>();
return customerRepository.FindByEmail(value.ToString()) == null;
}
}
I think it's a variation of the 'Static Gateway' approach mentioned by Mauricio Scheffer. I don't know if this is a good design or not. I'm not a huge fan of it, I'd rather the dependency was injected more 'elegantly', though I can't use constructor injection obviously, I'd like to use Property injection but can't work out a way to hook into the ASP.NET MVC framework code to do this (I've even pored though the MVC2 source code).
I was able to wire it up [using Autofac as it happens, but it's just constructor injection via the ASP.NET MVC DependencyResolver] in this answer, enabling one to write:
class MyModel
{
...
[Required, StringLength(42)]
[ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
public string MyProperty { get; set; }
....
}
public class MyDiDependentValidator : Validator<MyModel>
{
readonly IUnitOfWork _iLoveWrappingStuff;
public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
{
_iLoveWrappingStuff = iLoveWrappingStuff;
}
protected override bool IsValid(MyModel instance, object value)
{
var attempted = (string)value;
return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
}
}
With some helper classes (look over there), you wire it up e.g. in ASP.NET MVC like so in the Global.asax :-
DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
typeof(ValidatorServiceAttribute),
(metadata, context, attribute) =>
new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
Hmm.
Can you test the effect of removing the (string message) ctor, and see if that at least forces Castle to use the ctor with the Repostiory ?
Otherwise we call AddComponent(name, type, type). Other than that it really should work...
Also does this hint at my first idea ? How do I use Windsor to inject dependencies into ActionFilterAttributes

Categories