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)
感谢
您需要设置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(){}
如果遵循这些步骤,它应该可以工作(编辑、插入、删除等)