If I'm not mistaken, you will have to register your custom metadata provider to MVC explicitly:
ModelMetadataProviders.Current =
new MyMetadataProvider();
If you need this instance also to be injectable into types that are resolved from the container, you will also need to register it in the container:
ModelMetadataProviders.Current =
new MyMetadataProvider();
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
If you want the container to inject dependencies into your custom MyMetadataProvider, you'll need to do something like this:
container.RegisterSingle<ModelMetadataProvider, MyMetadataProvider>();
container.Verify();
// Call this after you're done configuring the container.
ModelMetadataProviders.Current =
container.GetInstance<ModelMetadataProvider>();
Since the ModelMetadataProviders.Current is a singleton, the ModelMetadataProvider must be a singleton, or at least, it should not be a problem for it to be cached for the lifetime of the application and accessed simultaniously from multiple threads. This might not be appropriate for your custom provider, when you inject dependencies into it (since those dependencies could have a shorter lifetime than the singleton lifestyle).
In that case you should create a proxy provider that calls back into the DependencyResolver:
public DependencyResolverModelMetadataProvider : ModelMetadataProvider
{
public override IEnumerable<ModelMetadata> GetMetadataForProperties(
object container, Type containerType)
{
return GetProvider().GetMetadataForProperties(
container, containerType);
}
public override ModelMetadata GetMetadataForProperty(
Func<object> modelAccessor, Type containerType, string propertyName)
{
return GetProvider().GetMetadataForProperty(
modelAccessor, containerType, propertyName);
}
public override ModelMetadata GetMetadataForType(
Func<object> modelAccessor, Type modelType)
{
return GetProvider().GetMetadataForType(
modelAccessor, modelType);
}
private static ModelMetadataProvider GetProvider()
{
return (ModelMetadataProvider)
DependencyResolver.Current.GetService(
typeof(ModelMetadataProvider));
}
}
Since this proxy will call into the DependencyResolver on each call (and contains no state), you can safely create a single instance and store it into the ModelMetadataProviders.Current property.
Your configuration will in that case look as follows:
// register the proxy that calls back into the container.
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
// Register it as transient.
container.Register<ModelMetadataProvider, MyMetadataProvider>();
If you want your custom provider to decorate the original provider, you will need to inject this orginal provider into a property of your custom provider (there are other ways, but this is the easiest thing to do):
var original = ModelMetadataProviders.Current;
// register the proxy that calls back into the container.
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
// Register it as transient.
container.Register<ModelMetadataProvider, MyMetadataProvider>();
container.RegisterInitializer<MyMetadataProvider>(prov =>
{
// The decorated provider is put as a property on the
// MyMetadataProvider class.
prov.DecoratedProvider = original;
});
An alternative approach would be to register the custom MyMetadataProvider as decorator class:
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
container.RegisterDecorator(
typeof(ModelMetadataProvider),
typeof(MyMetadataProvider));
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
By registering MyMetadataProvider as decorator, it will be wrapped around the original registered ModelMetadataProvider (which will be injected into the MyMetadataProvider. You'll need the SimpleInjector.Extensions.dll project to get the RegisterDecorator extensions.