Как реализовать пользовательский SiteMapNodeProvider
Я пытаюсь адаптировать MvcSiteMapProvider для создания крошек на основе некоторой информации, хранящейся в базе данных.
Ответ вэтот сообщение звучало многообещающе, поэтому я реализовал свой собственный SiteMapNodeProvider. Но тогда я не знал, как это сделать, поэтому вместо статического XML-файла используется недавно реализованный SiteMapNodeProvider ("Mvc.sitemap»).
Поскольку я использую SimpleInjector в своем проекте, я вызвал метод установки в моем уже существующем коде инициализации инъекции.
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), но все равно я получаю ошибки ... вот что я имею в моем 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,
allAssemblies,
new Type[0],
"^Composite");
container.Register();
// Visibility Providers
container.RegisterSingle(() =>
new SiteMapNodeVisibilityProviderStrategy(
container.GetAllInstances
().
ToArray(), string.Empty));
// Pass in the global controllerBuilder reference
container.RegisterSingle(() => ControllerBuilder.Current);
container.RegisterSingle();
container.RegisterSingle();
container.RegisterSingle(() =>
new ControllerTypeResolverFactory(new string[0],
container.GetInstance
(),
container.GetInstance
()));
// Configure Security
container.RegisterAll(typeof(AuthorizeAttributeAclModule), typeof(XmlRolesAclModule));
container.RegisterSingle(() => new CompositeAclModule(container.GetAllInstances().ToArray()));
// Setup cache
container.RegisterSingle(() => System.Runtime.Caching.MemoryCache.Default);
container.RegisterSingleOpenGeneric(typeof(ICacheProvider), typeof(RuntimeCacheProvider));
container.RegisterSingle(() => new RuntimeFileCacheDependency(absoluteFileName));
container.RegisterSingle(() => new CacheDetails(absoluteCacheExpiration, TimeSpan.MinValue, container.GetInstance()));
// Configure the visitors
container.RegisterSingle();
// Prepare for the sitemap node providers
container.RegisterSingle(
() => new SiteMapXmlReservedAttributeNameProvider(new string[0]));
container.RegisterSingle(() => new FileXmlSource(absoluteFileName));
// Register the sitemap node providers
container.RegisterSingle(() => container.GetInstance()
.Create(container.GetInstance()));
container.RegisterSingle(() => container.GetInstance()
.Create(includeAssembliesForScan));
// Register your custom sitemap node provider
container.RegisterSingle();
// Register the collection of sitemap node providers (including the custom one)
container.RegisterSingle(() => container.GetInstance()
.Create(new CompositeSiteMapNodeProvider(
container.GetInstance(),
container.GetInstance(),
container.GetInstance())));
container.RegisterAll(ResolveISiteMapBuilderSets(container, securityTrimmingEnabled, enableLocalization));
container.RegisterSingle(() => new SiteMapBuilderSetStrategy(container.GetAllInstances().ToArray()));
}
private static IEnumerable ResolveISiteMapBuilderSets(Container container, bool securityTrimmingEnabled, bool enableLocalization)
{
yield return new SiteMapBuilderSet(
"default",
securityTrimmingEnabled,
enableLocalization,
container.GetInstance(),
container.GetInstance());
}
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, container,
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);
}
}
но все же я получаю следующее исключение:
Не удалось найти регистрацию для типа DynamicSiteMapNodeBuilder и неявная регистрация не может быть выполнена. Конструктор типа DynamicSiteMapNodeBuilder содержит параметр типа ISiteMapNodeCreator с именем 'siteMapNodeCreator» это не зарегистрировано. Убедитесь, что ISiteMapNodeCreator зарегистрирован в контейнере, или измените конструктор DynamicSiteMapNodeBuilder.