asp.net универсальный репозиторий webapi и внедрение зависимостей с помощью resolver выдает ошибку

Я новичок в разработке шаблонов и внедрения зависимостей. Я использовал этот учебник для реализации моего проекта.

Архитектура приложений уровня предприятия с веб-API с использованием Entity Framework, общего шаблона репозитория и единицы работы

Решение, реализующее описанный выше шаблон дизайна учебника и внедрение зависимостей с помощью IOC

У меня есть два API-контроллера:SongController и PlaylistController, и, согласно учебному пособию, я реализовал до главы Resolve-зависимость-инъекция

Когда я запускаю свое приложение, мои два webapis 1) http://localhost:49544/api/song в songcontroller отлично работают с распознавателем 2) http://localhost:49544/api/playlist/8a79e096-052b-4057-9683-7a7443aa305a возвращает ошибку со следующим сообщением

{ "message": "Произошла ошибка.", "exceptionMessage": "Произошла ошибка при попытке создать контроллер типа 'PlayListController'. Убедитесь, что контроллер имеет открытый конструктор без параметров.", "exceptionType": "System.InvalidOperationException", "stackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(запрос HttpRequestMessage, HttpControllerDescriptor controllerDescriptor, тип controllerType)\r\n.ControlControllerControl Запрос HttpRequestMessage)\r\n в System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()", "innerException": { "message": " Произошла ошибка. "," ExceptionMessage ":" Разрешение сбой зависимости, type = 'MusicCloudWebApi.Controllers.API.PlayListController', name = '(none)'.\n Ошибка произошла во время: при разрешении. \ nException is: InvalidOperationException - Текущий тип, MusicCloud.Services.IPlayListServices, является интерфейсом и не может быть со nstructed. Вам не хватает сопоставления типов?\ N ----------------------------------------- ------ \ n В момент исключения контейнер был: \r\n Разрешить MusicCloudWebApi.Controllers.API.PlayListController,(нет)\r\n Разрешить параметр 'playListServices' конструктора MusicCloudWebApi.Controllers.API.PlayListController(MusicCloud.Services.IPlayListServices playListServices)\r\n Разрешение MusicCloud.Services.IPlayListServices,(нет)\r\n", "exceptionType": "Unity.Exceptions.ResolutionFailedException", "stackTrace. At "." UnityContainer.BuildUp(Тип typeToBuild, Существующий объект, Имя строки, ResolverOverride [] resolverOverrides)\r\n в Unity.UnityContainer.Resolve (Тип тип, Строковое имя, ResolverOverride [] resolverOverrides)\r\n в Unity.UnityRtainerEx (Контейнер IUnityContainer, Тип t, ResolverOverride [] переопределяет)\r\n в Unity.WebApi.UnityDependencyScope.GetService (Тип serviceType)\r\n в System.Web.Http.Dispatcher.DefaultHttpControllerActivator.RetInstance Запрос HttpRequestMessage, Type controllerType, Func1& 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. (Контекст IBuilderContext)\r\n в Unity.ObjectBuilder.BuildPlan.DynamicMethod.DynamicMethodBuildPlan.BuildUp (Контекст IBuilderContext)\r\n в Unity.ObjectBuilder.Strategies.BuildPlanStrategy.PertainUntity.Inte.StrategyChain.BuildUp(IBuilderContext builderContext)\r\n в Unity.Policy.BuildPlanPolicyExtensions.ExecuteBuildUp(IBuildPlanPolicy, контекст IBuilderContext)\r\n в Unity.UnityContainer, тип-объекта-объекта-наследования resolverOverrides)" } } }

ИД пользователя в таблице базы данных имеет тип nvarchar(128)

Я еще не реализовал аутентификацию, но жестко запрограммировал значение из таблицы в качестве параметра для webapi.

в чем проблема с ошибкой?

Исследователь проекта Resolver

Проект 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 следующий класс UnityConfig вызывается по адресу global.asax(UnityConfig.RegisterComponents();)

        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 у меня есть интерфейс IPlayListServices, который реализует PlayListServices

            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 ответ

@NightOwl888 Спасибо за подсказку о разрешении зависимостей. Я нашел, что вызывает проблему. Я пропустил, чтобы зарегистрировать IplaylistServices в dependencyresolver.cs

    registerComponent.RegisterType<IPlayListServices, PlayListServices>();
Другие вопросы по тегам