甚至可以设置MVC3来使用DependencyResolver来获得自定义的ModelMetadataProvider或ModelValidatorProvider吗?因为在这一点上,我无法通过DependencyResolver让它发挥作用。如果我通过global.asax中的代码显式地设置它,它将完美地工作,但是IoC只是默默地忽略了我的代码。我使用的是来自StructureMap的NuGet包,所以没有什么特别之处。
我现在通过global.asax Global.asax.cs的连接
ModelMetadataProviders.Current = new RedSandMetadataProvider(ModelMetadataProviders.Current);
ModelValidatorProviders.Providers.Add(new RedSandValidatorProvider((IUnitOfWork)DependencyResolver.Current.GetService(typeof (IUnitOfWork))));这些都是完美的。我必须将当前的ModelMetaDataProvider作为构造函数传递给我的自定义构造函数,因为一次只能连接一个ModelMetaDataProvider。因此,我通过检查方法参数来处理所需的调用,并让其余的通过基本实现。
我的ModelValidatorProviders使用一个IUnitOfWork对象,它有一个由nHibernate填充的会话属性。我这样做是因为我需要根据要验证的属性来确定在数据库中定义了哪些验证规则。
再说一次,这两种方法都很管用。但是,每次我尝试使用StructureMap来设置它们,以便它们可以被DependencyResolver使用时,我都无法得到想要的结果。以前有没有人这样做过,让它真正发挥作用?由于构造函数的参数,我需要做什么花哨的事情吗?是否有一个特定的生命周期,必须设置在这些类型的结构地图注册?我到处寻找这方面的例子,但它们都是指不适用于最终版本的MVC3的测试版或发布候选版本,或者是一些文章,说这是可能的,但实际上没有用一个例子来证明这一点。
我真的很感激任何人在这方面的帮助,因为我正在为这应该是多么的简单而努力,网络上的所有资源都说这是可能的,但我不能复制他们的任何说法。
更新
我使用的是StructureMap.MVC3 1.0.5,在注意到有更新之后,我刚刚更新到1.0.6,但是版本之间似乎没有太大差别?
我的StructureMap设置
public static IContainer Initialize() {
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
//scan.AssembliesFromApplicationBaseDirectory(); //Would this let us setup dependancy injection to dynamically load plugins?
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.LookForRegistries();
});
//x.For<IExample>().Use<Example>();
//x.For<ITempDataProvider>().Use( new CookieTempDataProvider(HttpContext.Current.Request.RequestContext.HttpContext));
//x.For<ModelMetadataProvider>().Singleton().Use(new RedSandMetadataProvider(ModelMetadataProviders.Current));
//x.For<ModelValidatorProvider>().Use<RedSandValidatorProvider>();
});
return ObjectFactory.Container;
}我允许通过使用WebActivator的包添加的Start()方法来设置依赖关系解析器。
您可以看到我试图注册我的元数据的行,以及验证器提供者注释掉的行。我不知道我的做法是否正确。我添加了要扫描注册表的调用,因为我有一个Registry配置,并将nhibernate添加到structuremap的容器中。
发布于 2011-03-30 18:38:42
我想我终于解决了自己的问题。我不知道验证提供程序现在为什么工作,可能是由于SmDependencyResolver.cs文件中的SmDependencyResolver.cs()方法的实现发生了变化,在更新StructureMap.MVC3引用之后我注意到了这一点,我不能百分之百确定。
但是ModelMetaDataProvider确实有一个问题。我从网络中使用的实现自定义ModelMetaDataProvider的示例让它在global.asax文件中设置如下。
ModelMetadataProviders.Current = new RedSandMetadataProvider(ModelMetadataProviders.Current);现在这个功能很好,只有在应用程序启动时才能点击一次。但是为了在IoC中实现它,我认为它由于ModelMetadataProviders.Current引用而导致了一个问题。我不知道为什么我从来没有得到错误,但出于一时冲动,我将其更改为实例化一个新的DataAnnotationsModelMetadataProvider()实例,这似乎解决了问题。我在结构图中注册的自定义ModelMetadataProvider现在看起来是这样的。
x.For<ModelMetadataProvider>().Use(new RedSandMetadataProvider(new DataAnnotationsModelMetadataProvider()));我希望这对其他可能有这个问题的人有帮助。
更新:跟进了Rudimenter的问题:实际上,我在控制提供者的生命周期方面也遇到了一些困难。我的ModelMetaDataprovider正在从数据库中提取信息来确定我要传递的模型元数据,但是由于MVC控制ModelMetadataProvider的方式,我的数据源的生存期与提供者的生存期不同步。最后,我承认我采取了懒惰的方式,在我的提供者中创建了一个私有属性,返回了我的数据源,它的生命周期由DependancyResolver控制。如果有人有任何建议,我愿意接受其他选择,但在当时,这是对我有效的解决方案。
private IMyMetadataRepository metadataRepository;
private IMyMetadataRepository MetadataRepository
{
get
{
if (metadataRepository == null || !metadataRepository.IsConnected)
this.metadataRepository = (IMyMetadataRepository)DependencyResolver.Current.GetService(typeof(IMyMetadataRepository));
return metadataRepository;
}
}更新:,很明显,这个问题一直保持着流量,所以我想我应该更新我的答案。根据其他人的评论,MVC只查询依赖解析器一次以获得ModelMetadataProvider的实现。在维护数据库存储库的生存期方面,我遇到了其他问题。此后,我将代码更改为如下,此后没有出现任何问题。
public class RedSandMetadataProvider : DataAnnotationsModelMetadataProvider
{
private IRepository<PseudoObjectStructure> StructureRepository
{
get
{
return (IRepository<IMyMetadataRepository>)DependencyResolver.Current.GetService(typeof(IRepository<IMyMetadataRepository>));
}
}
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
ModelMetadata metadata = null;
//logic for populating metadata here
return metadata;
}
}我建议您使用new ModelMetadata()设置起点,并根据需要对其进行修改。您可以随意地存储从数据库中检索到的对象,以确定在使用MetaData时使用metadata.AdditionalValues的情况,以防您也希望在ValidatorProvider中使用它。
https://stackoverflow.com/questions/5479527
复制相似问题