0

データベースに保存されている情報に基づいてパンくずリストを作成するように MvcSiteMapProvider を適応させようとしています。

この投稿の答えは有望に思えたので、独自の 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,
                allAssemblies,
                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",
                securityTrimmingEnabled,
                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, 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 のコンストラクターには、登録されていない「siteMapNodeCreator」という名前のタイプ ISiteMapNodeCreator のパラメーターが含まれています。ISiteMapNodeCreator がコンテナーに登録されていることを確認するか、DynamicSiteMapNodeBuilder のコンストラクターを変更してください。

4

1 に答える 1

1

まず、既存の DI セットアップと統合するには、 のMvcSiteMapProvider.MVC4.DI.SimpleInjector.Modules代わりにインストールする必要がありMvcSiteMapProvider.MVC4.DI.SimpleInjectorます。パッケージ マネージャー コンソールから次のコマンドを実行すると、ダウングレードできます。

PM> Uninstall-Package -Id MvcSiteMapProvider.MVC4.DI.SimpleInjector

依存関係をアンインストールしないでください。これにより、プロジェクトに DI 初期化コードのセットが 2 つなくなることが保証されます。アプリケーション全体で 1 つだけにする必要があります。

次に、DI と、MvcSiteMapProvider に必要なその他の初期化コードを接続する必要があります。readme ファイルには、これを行う方法が記載されています。既存の構成でそれを行う方法は次のとおりです。

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 と 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<ReflectionSiteMapNodeProvider>(), 
        container.GetInstance<CustomSiteMapNodeProvider>())));

IDynamicNodeProvider (文書化されています) は ISiteMapNodeProvider とほぼ同じことを行うため、代わりにそのオプションを使用できることに注意してください。主な違いは 3 つあります。

  1. IDynamicNodeProvider では、dynamicNodeProvider 属性を定義する「テンプレート」ノードを作成する必要があり、テンプレート ノード自体は SiteMap に含まれないため、動的ノードを処理する ISiteMapNodeProvider 実装と組み合わせて使用​​する必要があります (構築された-in ISiteMapNodeProvider はこれを自動的に行います)。
  2. IDynamicNodeProvider は、XmlSiteMapNodeProvider と ReflectionSiteMapNodeProvider の両方によって既に処理されているため、DI セットアップの一部である必要はありません。
  3. ISiteMapNodeProvider を使用すると、ISiteMapNode オブジェクトを直接操作し、IDynamicNodeProvider を使用すると抽象化 (DynamicNodeProvider) を操作し、自動的に変換が行われます。

SimpleInjector.Verify について

機能させたい場合はVerify()、MvcSiteMapProviderContainerInitializer の excludeTypes 配列に次を追加する必要があります。

typeof(SiteMapNodeCreator),
typeof(DynamicSiteMapNodeBuilder)

それらをモジュールに追加しましたが、Nuget パッケージの次のバージョンに含まれますが、これらのモジュールは更新されないため、手動で行う必要があります。

このVerify()メソッドは、コンテナーに登録されているすべてのもののインスタンスを作成しようとすることに注意してください。これには、実際にはコンテナーによって作成されないオブジェクトも含まれます。したがって、このVerify()方法を使用する場合は、誤って登録されないように注意する必要があります。これにより、規約ベースの登録がより困難になります。

于 2013-11-08T10:34:40.747 に答える