0

我是设计模式和依赖注入的新手。我使用本教程来实现我的项目。

使用实体框架、通用存储库模式和工作单元的具有 Web API 的企业级应用程序架构

使用 IOC 实现上述教程设计模式和依赖注入的解决方案

我有两个 API 控制器:SongController 和 PlaylistController,根据教程,我已经实现到Resolve-dependency-injection一章

当我运行我的应用程序时,我的两个 webapis 1)songcontroller中的http://localhost:49544/api/song与解析器配合得很好 2)http://localhost:49544/api/playlist/8a79e096-052b-4057-9683 -7a7443aa305a返回错误并显示以下消息

exceptionMessage": "依赖项解析失败,类型 = 'MusicCloudWebApi.Controllers.API.PlayListController',名称 = '(none)'。\n在解析时发生异常。\n异常是:InvalidOperationException - 当前类型,MusicCloud。 Services.IPlayListServices,是一个接口,不能构造。您是否缺少类型映射?\n---------------------------------------- ------\n异常发生时,容器为:\r\n Resolving MusicCloudWebApi.Controllers.API.PlayListController,(none)\r\n Resolving parameter 'playListServices' of constructor MusicCloudWebApi.Controllers.API .PlayListController(MusicCloud.Services.IPlayListServices playListServices)\r\n 正在解决 MusicCloud.Services.IPlayListServices,(none)\r\n", "exceptionType": "Unity.Exceptions.1& activator)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)", "innerException": { "message": "An error has occurred.", "exceptionMessage": "The current type, MusicCloud.Services.IPlayListServices, is an interface and cannot be constructed. Are you missing a type mapping?", "exceptionType": "System.InvalidOperationException", "stackTrace": " at Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context)\r\n at lambda_method(Closure , IBuilderContext )\r\n at Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicBuildPlanGenerationContext.<>c__DisplayClass16_0.<GetBuildMethod>b__0(IBuilderContext context)\r\n at Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)\r\n at Unity.ObjectBuilder.Strategies.BuildPlanStrategy.PreBuildUp(IBuilderContext context)\r\n at Unity.Container.StrategyChain.BuildUp(IBuilderContext builderContext)\r\n at Unity.Policy.BuildPlanPolicyExtensions.ExecuteBuildUp(IBuildPlanPolicy policy, IBuilderContext context)\r\n at Unity.ObjectBuilder.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey, Action1 childCustomizationBlock)\r\n Unity.ResolverPolicy.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)\r\n lambda_method(Closure , IBuilderContext)\r\n Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicBuildPlanGenerationContext.<>c__DisplayClass16_0.b__0 (IBuilderContext 上下文)\r\n 在 Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodBuildPlan.BuildUp(IBuilderContext 上下文)\r\n 在 Unity.ObjectBuilder.Strategies.BuildPlanStrategy.PreBuildUp(IBuilderContext 上下文)\r\n 在 Unity.Container .StrategyChain.BuildUp(IBuilderContext builderContext)\r\n 在 Unity.Policy.BuildPlanPolicyExtensions.ExecuteBuildUp(IBuildPlanPolicy 策略,IBuilderContext 上下文)\r\n 在 Unity.UnityContainer.BuildUp(类型 typeToBuild,现有对象,字符串名称,ResolverOverride[]解析器覆盖)"} } }

数据库表中的 userId 是 nvarchar(128) 类型

我尚未实现身份验证,但将表中的值作为参数硬编码到 webapi。

错误有什么问题?

解析器项目的解决方案资源管理器

解析器项目有以下接口和类

        using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace Resolver
    {
       public  interface IComponent
        {

            void SetUp(IRegisterComponent registerComponent);

        }
    }

            using System;
        using System.Collections.Generic;
        using System.ComponentModel.Composition.Hosting;
        using System.ComponentModel.Composition.Primitives;
        using System.Linq;
        using System.Reflection;
        using System.Text;
        using System.Web;
        using Unity;
        using Unity.Lifetime;

        namespace Resolver
        {

            public static class ComponentLoader
            {
                public static void LoadContainer(IUnityContainer container, string path, string pattern)
                {
                    var dirCat = new DirectoryCatalog(path, pattern);
                    var importDef = BuildImportDefinition();
                    try
                    {
                        using (var aggregateCatalog = new AggregateCatalog())
                        {
                            aggregateCatalog.Catalogs.Add(dirCat);

                            using (var componsitionContainer = new CompositionContainer(aggregateCatalog))
                            {
                                IEnumerable<Export> exports = componsitionContainer.GetExports(importDef);

                                IEnumerable<IComponent> modules =
                                    exports.Select(export => export.Value as IComponent).Where(m => m != null);

                                var registerComponent = new RegisterComponent(container);
                                foreach (IComponent module in modules)
                                {
                                    module.SetUp(registerComponent);
                                }
                            }
                        }
                    }
                    catch (ReflectionTypeLoadException typeLoadException)
                    {
                        var builder = new StringBuilder();
                        foreach (Exception loaderException in typeLoadException.LoaderExceptions)
                        {
                            builder.AppendFormat("{0}\n", loaderException.Message);
                        }

                        throw new TypeLoadException(builder.ToString(), typeLoadException);
                    }
                }

                private static ImportDefinition BuildImportDefinition()
                {
                    return new ImportDefinition(
                        def => true, typeof(IComponent).FullName, ImportCardinality.ZeroOrMore, false, false);
                }
            }

            internal class RegisterComponent : IRegisterComponent
            {
                private readonly IUnityContainer _container;

                public RegisterComponent(IUnityContainer container)
                {
                    this._container = container;
                    //Register interception behaviour if any
                }

                public void RegisterType<TFrom, TTo>(bool withInterception = false) where TTo : TFrom
                {
                    if (withInterception)
                    {
                        //register with interception
                    }
                    else
                    {
                        this._container.RegisterType<TFrom, TTo>();
                    }
                }

                public void RegisterTypeWithControlledLifeTime<TFrom, TTo>(bool withInterception = false) where TTo : TFrom
                {
                    this._container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
                }
            }

        }

            using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Threading.Tasks;

        namespace Resolver
        {
            /// <summary>
            /// Responsible for registering types in unity configuration by implementing IComponent
            /// </summary>
            public interface IRegisterComponent
            {
                /// <summary>
                /// Register type method
                /// </summary>
                /// <typeparam name="TFrom"></typeparam>
                /// <typeparam name="TTo"></typeparam>
                /// <param name="withInterception"></param>
                void RegisterType<TFrom, TTo>(bool withInterception = false) where TTo : TFrom;

                /// <summary>
                /// Register type with container controlled life time manager
                /// </summary>
                /// <typeparam name="TFrom"></typeparam>
                /// <typeparam name="TTo"></typeparam>
                /// <param name="withInterception"></param>
                void RegisterTypeWithControlledLifeTime<TFrom, TTo>(bool withInterception = false) where TTo : TFrom;

            }
        }

在 MusicWebAPI 项目解决方案中,在 global.asax(UnityConfig.RegisterComponents();) 处调用了以下类 UnityConfig

        using MusicCloud.Model;
        using MusicCloud.Services;
        using Resolver;
        using System.Web.Http;
        using System.Web.Mvc;
        using Unity;
        using Unity.Lifetime;
        using Unity.WebApi;

        namespace MusicCloudWebApi
        {
            public static class UnityConfig
            {
                public static void RegisterComponents()
                {
                    var container = BuildUnityContainer();


                    //  System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolver(container));
                    System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));

                    // register dependency resolver for WebAPI RC
                    GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
                    // Create the depenedency resolver.
                    //var resolver = new AutofacWebApiDependencyResolver(container);

                    // Configure Web API with the dependency resolver.
                    //GlobalConfiguration.Configuration.DependencyResolver = resolver;


                }

                private static IUnityContainer BuildUnityContainer()
                {
                    var container = new UnityContainer();

                    // register all your components with the container here
                    // it is NOT necessary to register your controllers

                    // e.g. container.RegisterType<ITestService, TestService>();       
                    // container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());

                    RegisterTypes(container);

                    return container;
                }


                public static void RegisterTypes(IUnityContainer container)
                {

                    //Component initialization via MEFE:\Susana\Portfolio\MusicCloud\MusicCloud\MusicCloudWebApi\bin\MusicCloudWebApi.dll
                    ComponentLoader.LoadContainer(container, ".\\bin", "MusicCloudWebApi.dll");
                    ComponentLoader.LoadContainer(container, ".\\bin", "MusicCloud.Services.dll");
                   // container.Register<DashboardDbContext>(
        //    new InjectionFactory(c => new DashboardDbContext()));


                }

            }

            internal class AutofacWebApiDependencyResolver
            {
                private IUnityContainer container;

                public AutofacWebApiDependencyResolver(IUnityContainer container)
                {
                    this.container = container;
                }
            }
        }

在 MusicCloud.Model 中,我有一个类名 DependencyResolver

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Threading.Tasks;
        using System.ComponentModel.Composition;
        using Resolver;
        using MusicCloud.Repository;
        using System.Data.Entity;
        using MusicCloud.Model;

        namespace MusicCloud.Model
        {
            /// <summary>
            /// a) Export in System.ComponentModel.Composition
            /// b)IComponent in Resolver in Resolver Project
            /// </summary>
            [Export(typeof(IComponent))]
            public class DependencyResolver : IComponent
            {
                public void SetUp(IRegisterComponent registerComponent)
                {
                    registerComponent.RegisterType<IUnitOfWork, UnitOfWork>();
                }
            }
        }

播放列表控制器(API)

         [System.Web.Http.HttpGet]
                //// GET api/playlist/abc
                public HttpResponseMessage GetPlayLists(string userId)
                {
                    userId = "8a79e096-052b-4057-9683-7a7443aa305a";
                    var playLists = _playListServices.GetAllPlayLists(userId);
                    if (playLists != null)
                    {
                        var playListEntities = playLists as List<PlayListEntity> ?? playLists.ToList();
                        if (playListEntities.Any())
                            return Request.CreateResponse(HttpStatusCode.OK, playListEntities);
                    }
                    return Request.CreateErrorResponse(HttpStatusCode.NotFound, "PlayLists not found");
                }

在 MusicCloud.Services 中,我有一个实现 PlayListServices 的接口 IPlayListServices

            using System;
            using System.Collections.Generic;
            using System.Linq;
            using System.Text;
            using System.Threading.Tasks;
            using MusicCloud.Entities;
            using MusicCloud.Model;
            using AutoMapper;
            using MusicCloud.Model.EFModel;
            using System.Transactions;


            namespace MusicCloud.Services
            {
                public class PlayListServices : IPlayListServices
                {
                    private readonly UnitOfWork _unitOfWork;

                    /// <summary>
                    /// Public constructor.
                    /// </summary>
                    //public PlayListServices()
                    //{
                    //    _unitOfWork = new UnitOfWork();
                    //}

                    public PlayListServices(UnitOfWork unitOfWork)
                    {
                        _unitOfWork = unitOfWork;
                    }



                    /// <summary>
                    /// Fetches playList details by id
                    /// </summary>
                    /// <param name="playListId"></param>
                    /// <returns></returns>
                    public PlayListEntity GetPlayListById(int playListId)
                    {
                        var playList = _unitOfWork.PlayListRepository.GetByID(playListId);
                        if (playList != null)
                        {
                            // Mapper.CreateMap<Song, SongEntity>();
                            Mapper.Initialize(cfg =>
                            {
                                cfg.CreateMap<PlayList, PlayListEntity>();

                                //Mapper.Map<Song, SongEntity>();
                            });

                            var playListModel = Mapper.Map<PlayList, PlayListEntity>(playList);
                            return playListModel;
                        }
                        return null;
                    }


                    /// <summary>
                    /// Fetches all the songs.
                    /// </summary>
                    /// <returns></returns>
                     public IEnumerable<PlayListEntity> GetAllPlayLists(string userId)
                   // public PlayListEntity GetAllPlayLists(int userId)

                    {

                        var playLists = _unitOfWork.PlayListRepository
                            .GetAllSongs(x =>
                  x.PlayListSongs.Select(report => report.UserId==userId)).ToList();
                                                   if (playLists.Any())
                        {

                            Mapper.Initialize(cfg =>
                            {
                                cfg.CreateMap<PlayList, PlayListEntity>();
                             });

                             var playListsModel = Mapper.Map<List<PlayList>, List<PlayListEntity>>(playLists);
                            return playListsModel;
                        }
                        return null;
                    }


                    /// <summary>
                    /// Creates a product
                    /// </summary>
                    /// <param name="productEntity"></param>
                    /// <returns></returns>
                    public int CreatePlaylist(PlayListEntity playListEntity)
                    {
                        ///remove
                        var userId = "1";
                          using (var scope = new TransactionScope())
                        {
                            var playList = new PlayList
                            {
                                Name = playListEntity.Name,
                                CreatedDate= playListEntity.CreatedDate,
                                ModifiedDate=playListEntity.ModifiedDate


                            };


                         _unitOfWork.PlayListRepository.Insert(playList);
                        _unitOfWork.Save();
                        scope.Complete();
                         return playList.Id;


                    }
                }

             }
            }
4

1 回答 1

0

@NightOwl888 感谢您对依赖解析器的提示。我找到了导致问题的原因。我错过了在 dependencyresolver.cs 中注册 IplaylistServices

    registerComponent.RegisterType<IPlayListServices, PlayListServices>();
于 2018-01-17T20:24:20.027 回答