使用解析器的asp.net webapi通用存储库和依赖注入会产生错误

时间:2018-01-17 14:58:01

标签: asp.net asp.net-web-api dependency-injection dependency-resolver

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

Enterprise Level Application Architecture with Web APIs using Entity Framework, Generic Repository Pattern and Unit of Work

Solution implementing the above tutorial design pattern and dependency injection with 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返回错误以及以下消息

  

{     “message”:“发生错误。”,     “exceptionMessage”:“尝试创建'PlayListController'类型的控制器时发生错误。确保控制器具有无参数的公共构造函数。”,     “exceptionType”:“System.InvalidOperationException”,     “stackTrace”:“在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor controllerDescriptor,类型controllerType)\ r \ n在System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\ r \ n在System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()“,     “innerException”:{       “message”:“发生错误。”,       “exceptionMessage”:“依赖项的解析失败,类型='MusicCloudWebApi.Controllers.API.PlayListController',name ='(none)'。\ n发生异常时:解析时。\ nException是:InvalidOperationException - 当前类型,MusicCloud .Services.IPlayListServices,是一个无法构造的接口。你是否缺少类型映射?\ n ---------------------------- ------------------- \ n在异常时,容器是:\ r \ n解析MusicCloudWebApi.Controllers.API.PlayListController,(无)\ r \ n解析构造函数MusicCloudWebApi.Controllers.API.PlayListController(MusicCloud.Services.IPlayListServices playListServices)的参数'playListServices'\ r \ n解析MusicCloud.Services.IPlayListServices,(none)\ r \ n“,       “exceptionType”:“Unity.Exceptions.ResolutionFailedException”,       “stackTrace”:“Unity.UnityContainer.BuildUp(Type typeToBuild,Object existing,String name,ResolverOverride [] resolverOverrides)\ r \ n在Unity.UnityContainer.Resolve(Type type,String name,ResolverOverride [] resolverOverrides)\ r \ n \ n在Unity.Web.Http.Dispatcher.DefaultHttpControllerActivator的Unity.UnityContainerExtensions.Resolve(IUnityContainer容器,Type t,ResolverOverride []覆盖)\ r \ n在Unity.WebApi.UnityDependencyScope.GetService(类型serviceType)\ r \ n中\ n \ n .GetInstanceOrActivator(HttpRequestMessage请求,类型controllerType,Func 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, Action 1 childCustomizationBlock)\ r \ n在Unity.ResolverPolicy.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)\ r \ n在lambda_method(Closure,IBuilderContext)\ r \ n at Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicBuildPlanGenerationContext。&lt;&gt; c__DisplayClass16_0.b__0(IBuilderContext context)\ r \ n在Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)\ r \ n Unity.ObjectBuilder.Strategies.BuildPrateStrategy.PreBuildUp(IBuilderContext context)\ r \ n在Unity.Container.StrategyChain.BuildUp(IBuilderContext builderContext)\ r \ n在Unity.Policy.BuildPlanPolicyExtensions.ExecuteBuildUp(IBuildPlanPolicy policy,IBuilderContext context) \ r \ n在Unity.UnityContainer.BuildUp(类型typeToBuild,Object existing,String name,ResolverOverride [] resolverOverrides)“       }     }   }

数据库表中的

userId的类型为nvarchar(128)

我还没有实现身份验证,但是将表中的值硬编码为webapi的参数。

错误有什么问题?

Resolver project's solution explorer

Resolver项目具有以下接口和类

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

playlistcontroller(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;


                    }
                }

             }
            }

1 个答案:

答案 0 :(得分:0)

@ NightOwl888感谢依赖修复程序的提示。我找到了导致这个问题的原因。我错过了在dependencyresolver.cs中注册IplaylistServices

    registerComponent.RegisterType<IPlayListServices, PlayListServices>();