MvcSiteMapProvider + Autofac + ISiteMapNodeVisibilityProvider из другой сборки
У меня самое сложное время, чтобы выяснить, как зарегистрировать пользовательский ISiteMapNodeVisibilityProvider (SiteMapNodeVisibilityProviderBase), используя Autofac в MvcSiteMapProvider.
Все работало нормально до того момента, когда я переместил провайдера видимости в другую сборку. Теперь, что бы я ни старался, я всегда получаю
Экземпляр поставщика видимости с именем "MyWasWorkingVisibilityProvider, MyNewAssembly" не найден. Проверьте конфигурацию DI, чтобы убедиться, что экземпляр поставщика видимости с этим именем существует и настроен правильно.
Согласно MvcSiteMapProvider
документация и код, кажется, мне нужно как-то в SiteMapNodeVisibilityProviderStrategy
... и я думаю, что я сделал это ниже... Но я не ниндзя Autofac.
В MvcSiteMapProviderModule.cs
Я добавил новую сборку везде, где я мог подумать...
string[] includeAssembliesForScan = new string[] { "MyOldAssembly", "MyNewAssembly" };
var allAssemblies = new Assembly[] { currentAssembly, siteMapProviderAssembly, typeof(MyWasWorkingVisibilityProvider).Assembly };
builder.RegisterType<SiteMapNodeVisibilityProviderStrategy>()
.As<ISiteMapNodeVisibilityProviderStrategy>()
.WithParameters(new List<Parameter> { new NamedParameter("defaultProviderName", string.Empty), new NamedParameter("siteMapNodeVisibilityProviders", new [] { new MyWasWorkingVisibilityProvider() }) });
builder.RegisterType<MyWasWorkingVisibilityProvider>()
.As<ISiteMapNodeVisibilityProvider>();
Но это все еще не работает.
Что бы это ни стоило, провайдер видимости для любого конкретного пункта меню сконфигурирован в базе данных, и вся структура меню загружена с провайдером динамических узлов, который также теперь находится в той же сборке, в которую я переместил провайдеров видимости. Поставщик динамических узлов, очевидно, работает, потому что он доходит до того, что пытается загрузить поставщиков видимости.
Я думал, что https://github.com/maartenba/MvcSiteMapProvider/issues/237 выглядело полезным, я не мог получить специфичный для провайдера видимости код для компиляции..
Другой пример, который не имел никакого эффекта: поставщик карты сайта MVC - производительность SiteMapPath очень низкая?
Так что я застрял сейчас. Я не волшебник с поставщиком Autofac ИЛИ MvcSiteMap, но, как я уже сказал, все работало нормально, пока я не переместил поставщик видимости в другую сборку.
Большое спасибо за ваше время и внимание! Я разочарован в этом пункте.
1 ответ
Просто догадка, но я подозреваю, что вы не обновили все visibilityProvider="MyNamespace.MyVisibilityProvider, MyAssembly"
ссылки в вашей конфигурации на новую сборку. SiteMapNodeVisibilityProviderBase использует полное имя типа.NET, чтобы найти правильный тип, включая имя сборки.
// From MvcSiteMapProvider.SiteMapNodeVisibilityProviderBase
public virtual bool AppliesTo(string providerName)
{
if (string.IsNullOrEmpty(providerName))
return false;
return this.GetType().Equals(Type.GetType(providerName, false));
}
Что касается регистрации DI, при условии, что вы оставили первый звонок CommonConventions.RegisterAllImplementationsOfInterface()
на месте, у вас было правильно с этой строкой:
var allAssemblies = new Assembly[] { currentAssembly, siteMapProviderAssembly, typeof(MyWasWorkingVisibilityProvider).Assembly };
Так что код должен выглядеть примерно так:
var allAssemblies = new Assembly[] { currentAssembly, siteMapProviderAssembly, typeof(MyWasWorkingVisibilityProvider).Assembly };
var excludeTypes = new Type[] {
// Use this array to add types you wish to explicitly exclude from convention-based
// auto-registration. By default all types that either match I[TypeName] = [TypeName] or
// I[TypeName] = [TypeName]Adapter will be automatically wired up as long as they don't
// have the [ExcludeFromAutoRegistrationAttribute].
//
// If you want to override a type that follows the convention, you should add the name
// of either the implementation name or the interface that it inherits to this list and
// add your manual registration code below. This will prevent duplicate registrations
// of the types from occurring.
// Example:
// typeof(SiteMap),
// typeof(SiteMapNodeVisibilityProviderStrategy)
};
var multipleImplementationTypes = new Type[] {
typeof(ISiteMapNodeUrlResolver),
typeof(ISiteMapNodeVisibilityProvider),
typeof(IDynamicNodeProvider)
};
// Matching type name (I[TypeName] = [TypeName]) or matching type name + suffix Adapter (I[TypeName] = [TypeName]Adapter)
// and not decorated with the [ExcludeFromAutoRegistrationAttribute].
CommonConventions.RegisterDefaultConventions(
(interfaceType, implementationType) => builder.RegisterType(implementationType).As(interfaceType).SingleInstance(),
new Assembly[] { siteMapProviderAssembly },
allAssemblies,
excludeTypes,
string.Empty);
// Multiple implementations of strategy based extension points (and not decorated with [ExcludeFromAutoRegistrationAttribute]).
CommonConventions.RegisterAllImplementationsOfInterface(
(interfaceType, implementationType) => builder.RegisterType(implementationType).As(interfaceType).SingleInstance(),
multipleImplementationTypes,
allAssemblies,
excludeTypes,
string.Empty);
// Registration of internal controllers
CommonConventions.RegisterAllImplementationsOfInterface(
(interfaceType, implementationType) => builder.RegisterType(implementationType).As(interfaceType).AsSelf().InstancePerDependency(),
new Type[] { typeof(IController) },
new Assembly[] { siteMapProviderAssembly },
new Type[0],
string.Empty);
Итак, короче говоря, ваша конфигурация DI верна, но конфигурация вашего узла атрибута / свойства VisibilityProvider - нет.
ПРИМЕЧАНИЕ. Нижняя строка предназначена только для сканирования атрибута [MvcSiteMapNode] на контроллерах, которые могут не входить в тот же проект, что и MvcSiteMapProvider, и не имеют ничего общего с настройкой поставщиков видимости.
string[] includeAssembliesForScan = new string[] { "MyOldAssembly", "MyNewAssembly" };