如果我没记错的话,您必须将您的自定义元数据提供程序显式注册到 MVC:
ModelMetadataProviders.Current =
new MyMetadataProvider();
如果您还需要将此实例注入到从容器解析的类型中,您还需要在容器中注册它:
ModelMetadataProviders.Current =
new MyMetadataProvider();
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
如果您希望容器将依赖项注入您的 custom MyMetadataProvider
,您需要执行以下操作:
container.RegisterSingle<ModelMetadataProvider, MyMetadataProvider>();
container.Verify();
// Call this after you're done configuring the container.
ModelMetadataProviders.Current =
container.GetInstance<ModelMetadataProvider>();
由于ModelMetadataProviders.Current
是单例,因此ModelMetadataProvider
必须是单例,或者至少,在应用程序的生命周期内对其进行缓存并从多个线程同时访问应该不是问题。当您将依赖项注入其中时,这可能不适合您的自定义提供程序(因为这些依赖项的生命周期可能比单例生活方式更短)。
在这种情况下,您应该创建一个代理提供者来回调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));
}
}
由于此代理将DependencyResolver
在每次调用时调用(并且不包含任何状态),因此您可以安全地创建单个实例并将其存储到ModelMetadataProviders.Current
属性中。
在这种情况下,您的配置将如下所示:
// register the proxy that calls back into the container.
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
// Register it as transient.
container.Register<ModelMetadataProvider, MyMetadataProvider>();
如果您希望您的自定义提供程序装饰原始提供程序,您需要将此原始提供程序注入您的自定义提供程序的属性中(还有其他方法,但这是最简单的方法):
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;
});
另一种方法是将自定义注册MyMetadataProvider
为装饰器类:
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
container.RegisterDecorator(
typeof(ModelMetadataProvider),
typeof(MyMetadataProvider));
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
通过注册MyMetadataProvider
为装饰器,它将包裹在原始注册的ModelMetadataProvider
(将被注入到MyMetadataProvider
. 你需要SimpleInjector.Extensions.dll
项目来获取RegisterDecorator
扩展。