I've got a service contract for a strongly-typed configuration:
public interface IConfigurationSource<TConfiguration> {
TConfiguration Current { get; }
}
and an implementation based on YAML files:
public class YamlFileConfigurationSource<TConfiguration>
: IConfigurationSource<TConfiguration> {
public YamlFileConfigurationSource(string fileName) { }
...
}
Now I'm trying to register the implementation within Autofac in a way that the fileName
parameter can be constructed based on the generic type of the requested service. So when a client requests YamlFileConfigurationSource<MyCustomConfigurationModel>
a path like MyCustomConfigurationModel.config can be provided.
I already tried with ContainerBuilder.RegisterGeneric()
, .WithConstructor()
and delegate factories, however I'm somehow unable to see how to access the generic type during registration.
YamlFileConfigurationSource
should not depends on fileName
you can get it using typeof(TConfiguration)
public class YamlFileConfigurationSource<TConfiguration>
: IConfigurationSource<TConfiguration> {
public YamlFileConfigurationSource() { }
public TConfiguration Current {
get {
String fileName = typeof(TConfiguration).Name + ".config";
// get config from fileName
}
}
}
If you want to dissociate the code where TConfiguration
is converted to a fileName you can introduce a new component.
public interface IConfigurationFileProvider<TConfiguration> {
String GetFileName();
}
public class SimpleConfigurationFileProvider<TConfiguration>
: IConfigurationFileProvider<TConfiguration> {
public String GetFileName() {
return typeof(TConfiguration) + ".config";
}
}
and add this dependency on the constructor of YamlFileConfigurationSource
The registration will look like this :
builder.RegisterGeneric(typeof(YamlFileConfigurationSource<>))
.As(typeof(IConfigurationSource<>));
builder.RegisterGeneric(typeof(SimpleConfigurationFileProvider<>))
.As(typeof(IConfigurationFileProvider<>));
By the way, for educational purpose, this is the way to do using the WithParameter
method
builder.RegisterGeneric(typeof(YamlFileConfigurationSource<>))
.As(typeof(IConfigurationSource<>))
.WithParameter((pi, c) => pi.Name == "fileName",
(pi, c) => pi.Member.DeclaringType.GetGenericArguments()[0].Name);
It should work, but it's a workaround, whereas the previous solution was more elegant.