asp.net-mvc-4 – 如何实现自定义SiteMapNodeProvider
我正在尝试调整MvcSiteMapProvider以基于存储在数据库中的一些信息创建面包屑.
this帖子的答案听起来很有希望所以我实现了自己的SiteMapNodeProvider.但后来我不知道如何连接,所以使用新实现的SiteMapNodeProvider而不是静态xml文件(“Mvc.sitemap”). 当我在我的项目中使用SimpleInjector时,我在已经存在的注入初始化代码中调用了setup方法. public static void Initialize() { Injection.Global = new Container(); InitializeContainer(Injection.Global); Injection.Global.RegisterMvcControllers(Assembly.GetExecutingAssembly()); Injection.Global.RegisterMvcAttributeFilterProvider(); Injection.Global.Verify(); DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(Injection.Global)); } private static void InitializeContainer(Container container) { // Setup configuration of DI MvcSiteMapProviderContainerInitializer.SetUp(container); //... register some other stuff for my project here ... } MvcSiteMapProviderContainerInitializer类由包创建:’Mvcsitemapprovider.mvc4.di.simpleinjector / 4.4.5′ 有谁知道如何让我的项目使用新创建的SiteMapNodeProvider? 编辑:我尝试了你的建议(甚至删除旧的DI东西,只使用了nuget-package中的那个),但我仍然得到错误… public static void SetUp(Container container) { bool securityTrimmingEnabled = false; bool enableLocalization = true; string absoluteFileName = HostingEnvironment.MapPath("~/Mvc.sitemap"); TimeSpan absoluteCacheExpiration = TimeSpan.FromMinutes(5); string[] includeAssembliesForScan = new string[] { "testsitemap" }; // Extension to allow resolution of arrays by GetAllInstances (natively based on IEnumerable). // source from: https://simpleinjector.codeplex.com/wikipage?title=CollectionRegistrationExtensions AllowToResolveArraysAndLists(container); var currentAssembly = typeof(MvcSiteMapProviderContainerInitializer).Assembly; var siteMapProviderAssembly = typeof(SiteMaps).Assembly; var allAssemblies = new Assembly[] { currentAssembly,siteMapProviderAssembly }; var excludeTypes = new Type[] { typeof (SiteMapNodeVisibilityProviderStrategy),typeof (SiteMapXmlReservedAttributeNameProvider),typeof (SiteMapBuilderSetStrategy),typeof (ControllerTypeResolverFactory),// Added 2013-06-28 by eric-b to avoid default singleton registration: typeof(XmlSiteMapController),// Added 2013-06-28 by eric-b for SimpleInjector.Verify method: typeof(PreservedRouteParameterCollection),typeof(MvcResolver),typeof(MvcSiteMapProvider.SiteMap),typeof(MetaRobotsValueCollection),typeof(RoleCollection),typeof(SiteMapPluginProvider),typeof(ControllerTypeResolver),typeof(RouteValueDictionary),typeof(AttributeDictionary),typeof(SiteMapNodeCreator) }; var multipleImplementationTypes = new Type[] { typeof (ISiteMapNodeUrlResolver),typeof (ISiteMapNodeVisibilityProvider),typeof (IDynamicNodeProvider) }; // Single implementations of interface with matching name (minus the "I"). CommonConventions.RegisterDefaultConventions( (interfaceType,implementationType) => container.RegisterSingle(interfaceType,implementationType),new Assembly[] { siteMapProviderAssembly },allAssemblies,excludeTypes,string.Empty); // Multiple implementations of strategy based extension points CommonConventions.RegisterAllImplementationsOfInterfaceSingle( (interfaceType,implementationTypes) => container.RegisterAll(interfaceType,implementationTypes),multipleImplementationTypes,new Type[0],"^Composite"); container.Register<XmlSiteMapController>(); // Visibility Providers container.RegisterSingle<ISiteMapNodeVisibilityProviderStrategy>(() => new SiteMapNodeVisibilityProviderStrategy( container.GetAllInstances <ISiteMapNodeVisibilityProvider>(). ToArray(),string.Empty)); // Pass in the global controllerBuilder reference container.RegisterSingle<ControllerBuilder>(() => ControllerBuilder.Current); container.RegisterSingle<IControllerBuilder,ControllerBuilderAdaptor>(); container.RegisterSingle<IBuildManager,BuildManagerAdaptor>(); container.RegisterSingle<IControllerTypeResolverFactory>(() => new ControllerTypeResolverFactory(new string[0],container.GetInstance <IControllerBuilder >(),container.GetInstance <IBuildManager>())); // Configure Security container.RegisterAll<IAclModule>(typeof(AuthorizeAttributeAclModule),typeof(XmlRolesAclModule)); container.RegisterSingle<IAclModule>(() => new CompositeAclModule(container.GetAllInstances<IAclModule>().ToArray())); // Setup cache container.RegisterSingle<System.Runtime.Caching.ObjectCache>(() => System.Runtime.Caching.MemoryCache.Default); container.RegisterSingleOpenGeneric(typeof(ICacheProvider<>),typeof(RuntimeCacheProvider<>)); container.RegisterSingle<ICacheDependency>(() => new RuntimeFileCacheDependency(absoluteFileName)); container.RegisterSingle<ICacheDetails>(() => new CacheDetails(absoluteCacheExpiration,TimeSpan.MinValue,container.GetInstance<ICacheDependency>())); // Configure the visitors container.RegisterSingle<ISiteMapNodeVisitor,UrlResolvingSiteMapNodeVisitor>(); // Prepare for the sitemap node providers container.RegisterSingle<ISiteMapXmlReservedAttributeNameProvider>( () => new SiteMapXmlReservedAttributeNameProvider(new string[0])); container.RegisterSingle<IXmlSource>(() => new FileXmlSource(absoluteFileName)); // Register the sitemap node providers container.RegisterSingle<XmlSiteMapNodeProvider>(() => container.GetInstance<XmlSiteMapNodeProviderFactory>() .Create(container.GetInstance<IXmlSource>())); container.RegisterSingle<ReflectionSiteMapNodeProvider>(() => container.GetInstance<ReflectionSiteMapNodeProviderFactory>() .Create(includeAssembliesForScan)); // Register your custom sitemap node provider container.RegisterSingle<ISiteMapNodeProvider,CustomSiteMapNodeProvider>(); // Register the collection of sitemap node providers (including the custom one) container.RegisterSingle<ISiteMapBuilder>(() => container.GetInstance<SiteMapBuilderFactory>() .Create(new CompositeSiteMapNodeProvider( container.GetInstance<XmlSiteMapNodeProvider>(),container.GetInstance<ReflectionSiteMapNodeProvider>(),container.GetInstance<CustomSiteMapNodeProvider>()))); container.RegisterAll<ISiteMapBuilderSet>(ResolveISiteMapBuilderSets(container,securityTrimmingEnabled,enableLocalization)); container.RegisterSingle<ISiteMapBuilderSetStrategy>(() => new SiteMapBuilderSetStrategy(container.GetAllInstances<ISiteMapBuilderSet>().ToArray())); } private static IEnumerable<ISiteMapBuilderSet> ResolveISiteMapBuilderSets(Container container,bool securityTrimmingEnabled,bool enableLocalization) { yield return new SiteMapBuilderSet( "default",enableLocalization,container.GetInstance<ISiteMapBuilder>(),container.GetInstance<ICacheDetails>()); } private static void AllowToResolveArraysAndLists(Container container) { container.ResolveUnregisteredType += (sender,e) => { var serviceType = e.UnregisteredServiceType; if (serviceType.IsArray) { RegisterArrayResolver(e,container,serviceType.GetElementType()); } else if (serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IList<>)) { RegisterArrayResolver(e,serviceType.GetGenericArguments()[0]); } }; } private static void RegisterArrayResolver(UnregisteredTypeEventArgs e,Container container,Type elementType) { var producer = container.GetRegistration(typeof(IEnumerable<>) .MakeGenericType(elementType)); var enumerableExpression = producer.BuildExpression(); var arrayMethod = typeof(Enumerable).GetMethod("ToArray") .MakeGenericMethod(elementType); var arrayExpression = Expression.Call(arrayMethod,enumerableExpression); e.Register(arrayExpression); } } 但我仍然得到以下异常:
解决方法
首先,要与现有的DI设置集成,您应该安装MvcSiteMapProvider.MVC4.DI.SimpleInjector.Modules而不是MvcSiteMapProvider.MVC4.DI.SimpleInjector.您可以通过从包管理器控制台运行此命令来降级:
PM> Uninstall-Package -Id MvcSiteMapProvider.MVC4.DI.SimpleInjector 一定不要卸载任何依赖项.这将确保您的项目中没有2组DI初始化代码 – 整个应用程序应该只有1组. 接下来,您需要连接DI以及MvcSiteMapProvider所需的其他一些初始化代码. readme file包含如何执行此操作的说明.以下是使用现有配置的方法. public static void Initialize() { Injection.Global = new Container(); InitializeContainer(Injection.Global); Injection.Global.RegisterMvcControllers(Assembly.GetExecutingAssembly()); Injection.Global.RegisterMvcAttributeFilterProvider(); Injection.Global.Verify(); DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(Injection.Global)); } private static void InitializeContainer(Container container) { // Setup configuration of DI (required) MvcSiteMapProviderContainerInitializer.SetUp(container); // Setup global sitemap loader (required) MvcSiteMapProvider.SiteMaps.Loader = container.GetInstance<ISiteMapLoader>(); // Check all configured .sitemap files to ensure they follow the XSD for MvcSiteMapProvider (optional) var validator = container.GetInstance<ISiteMapXmlValidator>(); validator.ValidateXml(HostingEnvironment.MapPath("~/Mvc.sitemap")); // Register the Sitemaps routes for search engines (optional) XmlSiteMapController.RegisterRoutes(RouteTable.Routes); // NOTE: You can put this in your RouteConfig.cs file if desired. //... register some other stuff for your project here ... } 如果/sitemap.xml端点不起作用,您可能还需要添加此行来注册XmlSiteMapController: Injection.Global.RegisterMvcControllers(typeof(MvcSiteMapProvider.SiteMaps).Assembly); 要实现ISiteMapNodeProvider,这里有一个例子:MvcSiteMapProvider ISiteMapBuilder in conjunction with IDynamicNodeProvider. 要注册自定义ISiteMapNodeProvider,您只需确保将其添加到SiteMapBuilder的构造函数中.您还可以根据需要从以下代码中排除现有的SiteMapNodeProviders. // Register the sitemap node providers container.RegisterSingle<XmlSiteMapNodeProvider>(() => container.GetInstance<XmlSiteMapNodeProviderFactory>() .Create(container.GetInstance<IXmlSource>())); container.RegisterSingle<ReflectionSiteMapNodeProvider>(() => container.GetInstance<ReflectionSiteMapNodeProviderFactory>() .Create(includeAssembliesForScan)); // Register your custom sitemap node provider container.RegisterSingle<ISiteMapNodeProvider,CustomSiteMapNodeProvider>(); // Register the collection of sitemap node providers (including the custom one) container.RegisterSingle<ISiteMapBuilder>(() => container.GetInstance<SiteMapBuilderFactory>() .Create(new CompositeSiteMapNodeProvider( container.GetInstance<XmlSiteMapNodeProvider>(),container.GetInstance<CustomSiteMapNodeProvider>()))); 请注意,IDynamicNodeProvider(已记录)与ISiteMapNodeProvider几乎完全相同,因此您可以使用该选项.主要有三个不同之处: >使用IDynamicNodeProvider,您必须创建一个定义dynamicNodeProvider属性的“模板”节点,并且模板节点本身不会包含在SiteMap中,因此它必须与处理动态节点的ISiteMapNodeProvider实现一起使用(内置的ISiteMapNodeProviders自动执行此操作). 关于SimpleInjector.Verify 如果要使Verify()工作,则需要将以下内容添加到MvcSiteMapProviderContainerInitializer中的excludeTypes数组中. typeof(SiteMapNodeCreator),typeof(DynamicSiteMapNodeBuilder) 我已将它们添加到模块中,并将在Nuget包的下一个版本中,但这些模块不会更新,因此您必须手动执行此操作. 请注意,Verify()方法尝试创建向容器注册的所有内容的实例 – 包括永远不会被现实世界中的容器创建的对象.因此,如果您使用Verify()方法,则必须更加勤奋,以免意外注册.这使得基于约定的注册更加困难. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – Spark View Engine的性能与ASP.NET相比如何
- asp.net-mvc-3 – html.TextBoxFor和html.Textbox,POSTing值
- asp.net-mvc-3 – mvc3在另一个内部嵌入了局部视图
- asp.net – 比较Razor vs ASPX语法
- 简单探讨一下.NET Core 3.0使用AspectCore的新姿势
- asp.net – 用于流量加密的公共反向代理背后的WCF
- asp.net – 为什么我无法访问usercontrol中的页面viewstate
- asp.net – 如何使用jQuery清除DIV中的所有文本框?
- ASP.NET OpenWebConfiguration失败
- asp.net-mvc – “test”服务器中的ASP.NET MVC运行时安装要
- asp.net – 分类失败.返回未最终内容
- asp.net-mvc-4 – Azure上的PushSharp ASP.net M
- asp.net-mvc – 如何在ASP.NET MVC中实现分页?
- 一步一步创建ASP.NET MVC5程序[Repository+Autof
- ASP.NET MVC – 将外部模型传递给编辑器模板
- asp.net-mvc – 根据活动页面有条件地显示部分视
- asp.net-mvc-3 – 不能使用NuGet PagedList ASP.
- 从ASP.NET Core Web API将多GB文件流式传输到AWS
- asp.net-mvc – 应用程序服务层作为静态类
- asp.net – SQL使用逗号分隔值和IN子句