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中的那个),但我仍然得到错误…
这是我在MvcSiteMapProviderContainerInitializer中的内容
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); } }
但我仍然得到以下异常:
No registration for type DynamicSiteMapNodeBuilder could be found and
an implicit registration could not be made. The constructor of the
type DynamicSiteMapNodeBuilder contains the parameter of type
ISiteMapNodeCreator with name ‘siteMapNodeCreator’ that is not
registered. Please ensure ISiteMapNodeCreator is registered in the
container,or change the constructor of DynamicSiteMapNodeBuilder.
解决方法
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自动执行此操作).
> IDynamicNodeProvider不需要成为DI设置的一部分,因为它已由XmlSiteMapNodeProvider和ReflectionSiteMapNodeProvider处理.
>使用ISiteMapNodeProvider,您直接使用ISiteMapNode对象,使用IDynamicNodeProvider处理抽象(DynamicNodeProvider)并且会自动进行转换.
关于SimpleInjector.Verify
如果要使Verify()工作,则需要将以下内容添加到MvcSiteMapProviderContainerInitializer中的excludeTypes数组中.
typeof(SiteMapNodeCreator),typeof(DynamicSiteMapNodeBuilder)
我已将它们添加到模块中,并将在Nuget包的下一个版本中,但这些模块不会更新,因此您必须手动执行此操作.
请注意,Verify()方法尝试创建向容器注册的所有内容的实例 – 包括永远不会被现实世界中的容器创建的对象.因此,如果您使用Verify()方法,则必须更加勤奋,以免意外注册.这使得基于约定的注册更加困难.