如何注册自定义SiteMapNodeProvider Unity DI

时间:2015-01-05 01:26:45

标签: c# asp.net-mvc dependency-injection mvcsitemapprovider

我安装了MvcSiteMapProvider MVC 5版本4.6.17,安装了MvcSiteMapProvider MVC 5统一模块,但我无法弄清楚如何注册我的ISiteMapNodeProvider实现。我假设我需要将我的类添加到MvcSiteMapProviderContainerExtension,但我尝试过的每次尝试都失败了。任何帮助将不胜感激。

更新
我试图创建一个ISiteMapNodeProvider的实现,它使用db来填充该站点地图。我还没有添加我的数据库调用,因为我认为这将是微不足道的。

public class CustomSiteMapNodeProvider : ISiteMapNodeProvider
{
    private readonly string sourceName = "CustomSiteMapNodeProvider";


    public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper)
    {
        var result = new List<ISiteMapNodeToParentRelation>();
        ...
        return result;
    }
}


我只对初始的MvcSiteMapProviderContainerExtension类略有改动,并且添加了ReservedAttributeName。

 public class MvcSiteMapProviderContainerExtension
    : UnityContainerExtension
{
    protected override void Initialize()
    {
        bool enableLocalization = true;
        string absoluteFileName = HostingEnvironment.MapPath("~/Mvc.sitemap");
        TimeSpan absoluteCacheExpiration = TimeSpan.FromMinutes(5);
        bool visibilityAffectsDescendants = true;
        bool useTitleIfDescriptionNotProvided = true;

        bool securityTrimmingEnabled = true;
        string[] includeAssembliesForScan = new string[] { "Ldi" };

        var currentAssembly = this.GetType().Assembly;
        var siteMapProviderAssembly = typeof(SiteMaps).Assembly;
        var allAssemblies = new Assembly[] { currentAssembly, siteMapProviderAssembly };
        var excludeTypes = new Type[] {};
        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) => this.Container.RegisterType(interfaceType, implementationType, new ContainerControlledLifetimeManager()),
            new Assembly[] { siteMapProviderAssembly },
            allAssemblies,
            excludeTypes,
            string.Empty);

        // Multiple implementations of strategy based extension points (and not decorated with [ExcludeFromAutoRegistrationAttribute]).
        CommonConventions.RegisterAllImplementationsOfInterface(
            (interfaceType, implementationType) => this.Container.RegisterType(interfaceType, implementationType, implementationType.Name, new ContainerControlledLifetimeManager()),
            multipleImplementationTypes,
            allAssemblies,
            excludeTypes,
            string.Empty);

        // TODO: Find a better way to inject an array constructor

        // Url Resolvers
        this.Container.RegisterType<ISiteMapNodeUrlResolverStrategy, SiteMapNodeUrlResolverStrategy>(new InjectionConstructor(
            new ResolvedArrayParameter<ISiteMapNodeUrlResolver>(this.Container.ResolveAll<ISiteMapNodeUrlResolver>().ToArray())
            ));

        // Visibility Providers
        this.Container.RegisterType<ISiteMapNodeVisibilityProviderStrategy, SiteMapNodeVisibilityProviderStrategy>(new InjectionConstructor(
            new ResolvedArrayParameter<ISiteMapNodeVisibilityProvider>(this.Container.ResolveAll<ISiteMapNodeVisibilityProvider>().ToArray()),
            new InjectionParameter<string>("MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider")
            ));

        // Dynamic Node Providers
        this.Container.RegisterType<IDynamicNodeProviderStrategy, DynamicNodeProviderStrategy>(new InjectionConstructor(
            new ResolvedArrayParameter<IDynamicNodeProvider>(this.Container.ResolveAll<IDynamicNodeProvider>().ToArray())
            ));


        // Pass in the global controllerBuilder reference
        this.Container.RegisterInstance<ControllerBuilder>(ControllerBuilder.Current);

        this.Container.RegisterType<IControllerTypeResolverFactory, ControllerTypeResolverFactory>(new InjectionConstructor(
            new List<string>(),
            new ResolvedParameter<IControllerBuilder>(),
            new ResolvedParameter<IBuildManager>()));

        // Configure Security

        // IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
        this.Container.RegisterType<IAclModule, AuthorizeAttributeAclModule>("authorizeAttribute");
        this.Container.RegisterType<IAclModule, XmlRolesAclModule>("xmlRoles");
        this.Container.RegisterType<IAclModule, CompositeAclModule>(new InjectionConstructor(new ResolvedArrayParameter<IAclModule>(
            new ResolvedParameter<IAclModule>("authorizeAttribute"),
            new ResolvedParameter<IAclModule>("xmlRoles"))));

        this.Container.RegisterInstance<System.Runtime.Caching.ObjectCache>(System.Runtime.Caching.MemoryCache.Default);
        this.Container.RegisterType(typeof(ICacheProvider<>), typeof(RuntimeCacheProvider<>));
        this.Container.RegisterType<ICacheDependency, RuntimeFileCacheDependency>(
            "cacheDependency", new InjectionConstructor(absoluteFileName));

        this.Container.RegisterType<ICacheDetails, CacheDetails>("cacheDetails",
            new InjectionConstructor(absoluteCacheExpiration, TimeSpan.MinValue, new ResolvedParameter<ICacheDependency>("cacheDependency")));

        // Configure the visitors
        this.Container.RegisterType<ISiteMapNodeVisitor, UrlResolvingSiteMapNodeVisitor>();

        // Prepare for the sitemap node providers
        this.Container.RegisterType<IXmlSource, FileXmlSource>("file1XmlSource", new InjectionConstructor(absoluteFileName));
        this.Container.RegisterType<IReservedAttributeNameProvider, ReservedAttributeNameProvider>(new InjectionConstructor(new List<string>() { "type" }));

        // IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
        // Register the sitemap node providers
        this.Container.RegisterInstance<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1", this.Container.Resolve<XmlSiteMapNodeProviderFactory>().Create(this.Container.Resolve<IXmlSource>("file1XmlSource")), new ContainerControlledLifetimeManager());
        this.Container.RegisterInstance<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1", this.Container.Resolve<ReflectionSiteMapNodeProviderFactory>().Create(includeAssembliesForScan), new ContainerControlledLifetimeManager());
        this.Container.RegisterType<ISiteMapNodeProvider, CompositeSiteMapNodeProvider>(new InjectionConstructor(new ResolvedArrayParameter<ISiteMapNodeProvider>(
            new ResolvedParameter<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1"),
            new ResolvedParameter<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1"))));

        // Configure the builders
        this.Container.RegisterType<ISiteMapBuilder, SiteMapBuilder>();

        // Configure the builder sets
        this.Container.RegisterType<ISiteMapBuilderSet, SiteMapBuilderSet>("builderSet1",
            new InjectionConstructor(
                "default",
                securityTrimmingEnabled,
                enableLocalization,
                visibilityAffectsDescendants,
                useTitleIfDescriptionNotProvided,
                new ResolvedParameter<ISiteMapBuilder>(),
                new ResolvedParameter<ICacheDetails>("cacheDetails")));

        this.Container.RegisterType<ISiteMapBuilderSetStrategy, SiteMapBuilderSetStrategy>(new InjectionConstructor(
            new ResolvedArrayParameter<ISiteMapBuilderSet>(new ResolvedParameter<ISiteMapBuilderSet>("builderSet1"))));
    }
}


我想我只需要通过将其作为参数传递给CompositeSiteMapNodeProvider来注册我的CustomSiteMapNodeProvider类,但我尝试的所有内容都失败了。

1 个答案:

答案 0 :(得分:0)

你是对的,你只需要将CustomSiteMapNodeProvider实例传递给CompositeSiteMapNodeProvider。

// IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
// Register the sitemap node providers
this.Container.RegisterInstance<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1", this.Container.Resolve<XmlSiteMapNodeProviderFactory>().Create(this.Container.Resolve<IXmlSource>("file1XmlSource")), new ContainerControlledLifetimeManager());
this.Container.RegisterInstance<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1", this.Container.Resolve<ReflectionSiteMapNodeProviderFactory>().Create(includeAssembliesForScan), new ContainerControlledLifetimeManager());
// Register your custom SiteMapNodeProvider, and give it a name (required).
this.Container.RegisterType<ISiteMapNodeProvider, CustomSiteMapNodeProvider>("customSiteMapNodeProvider");
this.Container.RegisterType<ISiteMapNodeProvider, CompositeSiteMapNodeProvider>(new InjectionConstructor(new ResolvedArrayParameter<ISiteMapNodeProvider>(
    new ResolvedParameter<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1"),
    new ResolvedParameter<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1"),
    // Resolve your custom SiteMapNodeProvider instance.
    // Note the name must match the name above, and naming the registration is required in
    // Unity in order to resolve more than one implementation of an interface.
    new ResolvedParameter<ISiteMapNodeProvider>("customSiteMapNodeProvider"))));

或者,如果其他所有方法都失败了,穷人的方式就是这样做的:

// IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
// Register the sitemap node providers
this.Container.RegisterInstance<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1", this.Container.Resolve<XmlSiteMapNodeProviderFactory>().Create(this.Container.Resolve<IXmlSource>("file1XmlSource")), new ContainerControlledLifetimeManager());
this.Container.RegisterInstance<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1", this.Container.Resolve<ReflectionSiteMapNodeProviderFactory>().Create(includeAssembliesForScan), new ContainerControlledLifetimeManager());
this.Container.RegisterType<ISiteMapNodeProvider, CompositeSiteMapNodeProvider>(new InjectionConstructor(new ResolvedArrayParameter<ISiteMapNodeProvider>(
    new ResolvedParameter<ISiteMapNodeProvider>("xmlSiteMapNodeProvider1"),
    new ResolvedParameter<ISiteMapNodeProvider>("reflectionSiteMapNodeProvider1"),
    new CustomSiteMapNodeProvider())));

基本上,这就是Unity在这种情况下所做的一切。但是如果您的CustomSiteMapNodeProvider具有依赖关系,您应该尝试将其注册到容器中,以便可以自动注入它们。