简体   繁体   English

如何注册自定义SiteMapNodeProvider Unity DI

[英]How to register custom SiteMapNodeProvider Unity DI

I have MvcSiteMapProvider MVC 5 version 4.6.17 with MvcSiteMapProvider MVC 5 unity modules installed, but I can't figure out how to register my implementation of ISiteMapNodeProvider. 我安装了MvcSiteMapProvider MVC 5版本4.6.17,并安装了MvcSiteMapProvider MVC 5统一模块,但是我不知道如何注册ISiteMapNodeProvider的实现。 I assume I need to add my class to MvcSiteMapProviderContainerExtension but every attempt I have tried has failed. 我假设我需要将类添加到MvcSiteMapProviderContainerExtension,但是我尝试过的每一次尝试都失败了。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Update 更新资料
I'm trying to create an implementation of ISiteMapNodeProvider that uses a db to populate that site map. 我正在尝试创建使用数据库填充该站点地图的ISiteMapNodeProvider的实现。 I haven't added my db calls yet because I assume this will be trivial. 我尚未添加数据库调用,因为我认为这将是微不足道的。

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


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


I've only made a slight change to the initial MvcSiteMapProviderContainerExtension class and that was adding a ReservedAttributeName. 我仅对初始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"))));
    }
}


I think I just need to register my CustomSiteMapNodeProvider class by passing it to the CompositeSiteMapNodeProvider as a parameter, but everything I tried has failed. 我想我只需要通过将我的CustomSiteMapNodeProvider类作为参数传递给CompositeSiteMapNodeProvider进行注册,但是我尝试的所有操作都失败了。

You are correct, you just need to pass the CustomSiteMapNodeProvider instance to the CompositeSiteMapNodeProvider. 没错,您只需要将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"))));

Or, the poor man's way of doing it if all else fails: 或者,如果其他所有方法都失败了,穷人的做法是:

// 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())));

Basically, that is all Unity is doing in this scenario. 基本上,这就是Unity在这种情况下要做的。 But if your CustomSiteMapNodeProvider has dependencies, you should try to register it with the container so they can be injected automatically. 但是,如果您的CustomSiteMapNodeProvider具有依赖项,则应尝试在容器中注册它,以便可以自动注入它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM