I have a problem when trying to inject one dependency into the one I’m currently registering. I have an application that upon starting inits a bootstrap loader to read from a settings file, and then creates an object using reflection from a particular value in this settings file. I’ll try and let the code do the talking here.
Settings file
The settings file is a plain old XML file, that serializes / deserializes to an object called BootstrapSettings which adheres to the following contract:
public interface IBootstrapSettings
{
string Get(string key);
void Set(string key, string value);
}
Within this settings file, I have a particular key that identifies what IEncryptor I intend to use for this application, at the moment I have a choice of PlainTextEncryptor or TDESEncryptor, the latter reads a passphrase from the settings file and so in its constructor I am passing an instance of IBootstrapSettings to read this passphrase from the settings file. At the moment I am injecting an instance of IBootstrapSettings into each encryptor – even though PlainTextEncryptor doesn’t use it. I’m doing this because I’m having to create this instance using reflection and don’t know how I can differentiate between a constructor that doesn’t take a parameter and a constructor that does when creating an IEncryptor type (but this is another question I suppose).
IEncryptor constructors
The following are the constructors for each IEncryptor I currently have.
public sealed class PlainTextEncryptor : IEncryptor
{
private readonly IBootstrapSettings _bootstrapSettings;
public PlainTextEncryptor(IBootstrapSettings bootstrapSettings)
{
_bootstrapSettings = bootstrapSettings;
}
}
public sealed class TDESEncryptor : IEncryptor
{
private readonly IBootstrapSettings _bootstrapSettings;
public TDESEncryptor(IBootstrapSettings bootstrapSettings)
{
_bootstrapSettings = bootstrapSettings;
}
}
Injection
Onto how I’m setting up my dependencies. I have an Autofac module that creates the bootstrap dependencies before anything else is created – it looks like this:
public sealed class BootstrapSettingsModule : Autofac.Module
{
private readonly string _filePath;
public BootstrapSettingsModule(string filePath)
{
_filePath = filePath;
}
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.Register(c => new BootstrapSettings(_bootstrapSettingsPath))
.As<IBootstrapSettings>()
.SingleInstance();
builder.Register(c => (IEncryptor)Activator.CreateInstance(Type.GetType(c.Resolve<IBootstrapSettings>().Get("encryptionprovider")), args: new { bootstrapSettings = c.Resolve<IBootstrapSettings>() }))
.As<IEncryptor>()
.SingleInstance();
}
}
Now this executes fine, the problem occurs when I try to .Resolve an instance of IEncryptor I am getting the error Constructor on type ‘whatever encryptor type’ not found. I assume this is because Autofac cannot resolve my IBootstrapSettings and because I have no default parameterless constructor on my IEncryptor it’s throwing a fit.
I’m at a bit of a loss as to what to do here, am I doing something wrong by specifying the IBootstrapSettings as a single instance… or do I just not understand Autofac’s binding correctly? Appreciate any help as always!
I don’t understand why you are not just using the facilities of Autofac.
This would give you the additional advantage that you wouldn’t need to have a constructor with an
IBootstrapSettingsparameter in every encryptor. You would need it just in those that really make use of that parameter.