Unity引导程序(Unity.Mvc),Unity 3,Mvc 5,EF6接收错误:控制器上的无参数公共构造函数

本文关键字:Unity Mvc 构造函数 控制器 参数 引导程序 EF6 错误 | 更新日期: 2023-09-27 17:59:01

好吧,在搜索了谷歌、这里和几个ASP/MVC论坛之后,我一定要问我到底做错了什么。

我的应用程序有了一个良好的开端,对DI、IoC有了良好的理解,并且正在使用Repository、Service和UnitOfWork模式。当我试图加载一个需要Unity DI的控制器时,就好像Unity没有解决任何注册项目,或者我做得很差。从我能看到的这个版本的所有例子中(而不是创建Bootstrap.cs文件的版本,然后从Global.asax调用),我正在做其他人所做的事情,而不是Unity的爱。

我的核心问题是:我是否设置/配置了Unity,以便根据需要将项目注入控制器构造函数。如果我有,有什么想法为什么它不像我看到的例子那样起作用吗?

我不断收到这样的错误:AssetController需要一个无参数的公共构造函数。如果我加了一个,它就会在没有DI的情况下使用它,如果我不加,它就会大喊没有

谢谢,下面的代码。

UnityConfig.cs

namespace CARS.web.App_Start
{
    /// <summary>
    /// Specifies the Unity configuration for the main container.
    /// </summary>
    public class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });
        /// <summary>
        /// Gets the configured Unity container.
        /// </summary>
        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion
        /// <summary>Registers the type mappings with the Unity container.</summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
        /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
            // container.LoadConfiguration();
            // TODO: Register your types here
            // container.RegisterType<IProductRepository, ProductRepository>();
            container.RegisterType<IDataContext, CARSDEMOContext>(new PerRequestLifetimeManager())
                .RegisterType<IAssetService, AssetService>()
                .RegisterType<IUnitOfWork, UnitOfWork>()
                .RegisterType<IRepository<Asset>, Repository<Asset>>();
                //.RegisterType<AssetController>(new InjectionConstructor(typeof(IAssetService), typeof(IUnitOfWork)));
        }
    }
}

AssetController.cs(我正在执行注入参数的构造函数部分)

namespace CARS.web.Controllers
{
    public class AssetController : Controller
    {
        private readonly IAssetService _assetService;
        private readonly IUnitOfWork _unitOfWork;
        public AssetController(IAssetService assetService, IUnitOfWork unitOfWork)
        {
            _assetService = assetService;
            _unitOfWork = unitOfWork;
        }
        //other methods for CRUD etc stripped for brevity
    }
}

IAssetService.cs(第一个参数是assetService)

namespace CARS.service
{
    public interface IAssetService : IService<Asset>
    {
        Task<IEnumerable<Asset>> GetAsync();
        Task<Asset> FindAsync(Guid id);
        Asset Add(Asset asset);
        Asset Update(Asset asset);
        void Remove(Guid id);
    }
}

AssetService.cs(IAssetService交互的具体实现)

namespace CARS.service
{

    public class AssetService : Service<Asset>, IAssetService
    {
        private readonly IRepositoryAsync<Asset> _repository;
        public AssetService(IRepositoryAsync<Asset> repository) : base(repository)
        {
            _repository = repository;
        }
        public Task<IEnumerable<Asset>> GetAsync()
        {
            //return _repository.Query().SelectAsync();
            return _repository.Query().SelectAsync();
        }
        public Task<Asset> FindAsync(Guid id)
        {
            return _repository.FindAsync(id);
        }
        public Asset Add(Asset asset)
        {
            _repository.Insert(asset);
            return asset;
        }
        public Asset Update(Asset asset)
        {
            _repository.Update(asset);
            return asset;
        }
        public void Remove(Guid id)
        {
            _repository.Delete(id);
        }
    }
}

IUnitOfWork.cs(这来自Long Le的通用UofW和存储库-http://genericunitofworkandrepositories.codeplex.com/)

namespace Repository.Pattern.UnitOfWork
{
    public interface IUnitOfWork : IDisposable
    {
        int SaveChanges();
        Task<int> SaveChangesAsync();
        void Dispose(bool disposing);
        IRepository<TEntity> Repository<TEntity>() where TEntity : IObjectState;
        void BeginTransaction();
        bool Commit();
        void Rollback();
    }
}

UnitOfWork.cs(再次来自Long Le的框架)

namespace Repository.Pattern.Ef6
{
    public class UnitOfWork : IUnitOfWork, IUnitOfWorkAsync
    {
        #region Private Fields
        private readonly IDataContextAsync _dataContext;
        private bool _disposed;
        private ObjectContext _objectContext;
        private Dictionary<string, object> _repositories;
        private DbTransaction _transaction;
        #endregion Private Fields
        #region Constuctor/Dispose
        public UnitOfWork(IDataContextAsync dataContext)
        {
            _dataContext = dataContext;
        }
        public void Dispose()
        {
            if (_objectContext != null && _objectContext.Connection.State == ConnectionState.Open)
                _objectContext.Connection.Close();
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        public virtual void Dispose(bool disposing)
        {
            if (!_disposed && disposing)
                _dataContext.Dispose();
            _disposed = true;
        }
        #endregion Constuctor/Dispose
        public int SaveChanges()
        {
            return _dataContext.SaveChanges();
        }
        public IRepository<TEntity> Repository<TEntity>() where TEntity : IObjectState
        {
            return RepositoryAsync<TEntity>();
        }
        public Task<int> SaveChangesAsync()
        {
            return _dataContext.SaveChangesAsync();
        }
        public Task<int> SaveChangesAsync(CancellationToken cancellationToken)
        {
            return _dataContext.SaveChangesAsync(cancellationToken);
        }
        public IRepositoryAsync<TEntity> RepositoryAsync<TEntity>() where TEntity : IObjectState
        {
            if (_repositories == null)
                _repositories = new Dictionary<string, object>();
            var type = typeof (TEntity).Name;
            if (_repositories.ContainsKey(type))
                return (IRepositoryAsync<TEntity>) _repositories[type];
            var repositoryType = typeof (Repository<>);
            _repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof (TEntity)), _dataContext, this));
            return (IRepositoryAsync<TEntity>) _repositories[type];
        }
        #region Unit of Work Transactions
        public void BeginTransaction()
        {
            _objectContext = ((IObjectContextAdapter) _dataContext).ObjectContext;
            if (_objectContext.Connection.State != ConnectionState.Open)
            {
                _objectContext.Connection.Open();
                _transaction = _objectContext.Connection.BeginTransaction();
            }
        }
        public bool Commit()
        {
            _transaction.Commit();
            return true;
        }
        public void Rollback()
        {
            _transaction.Rollback();
            ((DataContext)_dataContext).SyncObjectsStatePostCommit();
        }
        #endregion
        // Uncomment, if rather have IRepositoryAsync<TEntity> IoC vs. Reflection Activation
        //public IRepositoryAsync<TEntity> RepositoryAsync<TEntity>() where TEntity : EntityBase
        //{
        //    return ServiceLocator.Current.GetInstance<IRepositoryAsync<TEntity>>();
        //}
    }
} 

更新为包括UnityMvcActivator.cs的SetResolver信息

using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(CARS.web.App_Start.UnityWebActivator), "Start")]
namespace CARS.web.App_Start
{
    /// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
    public static class UnityWebActivator
    {
        /// <summary>Integrates Unity when the application starts.</summary>
        public static void Start() 
        {
            var container = UnityConfig.GetConfiguredContainer();
            FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
            FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
            // TODO: Uncomment if you want to use PerRequestLifetimeManager
             Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
        }
    }
}

我已经阅读/尝试了以下信息/数据,但没有什么可以修复它:

类型IUserStore"1"没有可访问的构造函数

如何将MVC 5身份验证添加到Unity IoC?

未使用Unity[MVC 5]解决的类型

我已经准备好了,必须为Unity编写一个ControllerFactory才能做到这一点,但当我发现的所有示例都只是注册了配置,并且注入显然发生在控制器和其他需要的类上时,这似乎是一项艰巨的工作。

最后是错误:

The following server error was encountered: 
An error occurred when trying to create a controller of type           'CARS.web.Controllers.AssetController'. Make sure that the controller has a parameterless     public constructor.Details are: 
at     System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext    requestContext, Type controllerType) at    System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext,     String controllerName) at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase     httpContext, IController& controller, IControllerFactory& factory) at     System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback     callback, Object state) at     System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionSte    p.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&     completedSynchronously)

感谢

Unity引导程序(Unity.Mvc),Unity 3,Mvc 5,EF6接收错误:控制器上的无参数公共构造函数

您需要设置DependencyResolver。我看不到你提供的示例中的代码。

一旦设置了UnityContainer并注册了类型,就需要设置System.Web.MVC.DependencyResolver.

 DependencyResolver.SetResolver(new UnityDependencyResolver(container));

您可能错过了(像我一样)在UnityConfig.cs中注册异步类型
检查你是否有这个:

container.RegisterType<IUnitOfWork, UnitOfWork>(new PerRequestLifetimeManager())
            .RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager())
            .RegisterType<IDataContextAsync, SomeDBContext>(new PerRequestLifetimeManager())
            .RegisterType<IDataContext, SomeDBContext>(new PerRequestLifetimeManager())
            .RegisterType<ISomeService, SomeService>(new PerRequestLifetimeManager())
            .RegisterType<IRepositoryAsync<Some>, Repository<Some>>(new PerRequestLifetimeManager());

1:在文件UnityMvcActivator中取消注释此行:

Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

2:使用Unity+UnitOfwork+Repository进行基本注册这必须存在于文件:UnityConfig:中

container.RegisterType<IDataContextAsync, KlussendirectContext>(new PerRequestLifetimeManager());
container.RegisterType<IDataContext, KlussendirectContext>(new PerRequestLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerRequestLifetimeManager());
container.RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager());

3:当您在控制器(api)中使用依赖注入时,应该存在一个无参数构造函数:例如

 public MyNameController() : base(){}

如果遵循这些步骤,它应该可以工作(编辑、插入、删除等)