Reputation: 703
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.
Upvotes: 1
Views: 81
Reputation: 16192
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.
Upvotes: 2