Asp.net-Mvc-4
Autofac 和 ASP .Net MVC 4 Web API
我在我的 ASP .Net MVC 4 項目中使用Autofac for IoC。Autofac 在初始化儲存庫並將其傳遞給API Controller時遇到了一些麻煩。
我確定我的配置中遺漏了一些東西。
這是我導航到時遇到的錯誤:
https://localhost:44305/api/integration<Error> <Message>An error has occurred.</Message> <ExceptionMessage> None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'EL.Web.Controllers.API.IntegrationController' can be invoked with the available services and parameters: Cannot resolve parameter 'EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration] repository' of constructor 'Void .ctor(EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration])'. </ExceptionMessage> <ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType> <StackTrace> at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters) at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters) at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType) at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) </StackTrace> </Error>以下是一些相關的程式碼:
IoC 引導程序:
public static class Bootstrapper { public static void Initialize() { var builder = new ContainerBuilder(); builder.RegisterControllers(Assembly.GetExecutingAssembly()); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.Register(x => new SharePointContext(HttpContext.Current.Request)).As<ISharePointContext>().SingleInstance(); builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>(); builder.RegisterType<SharePointContextFilter>().SingleInstance(); builder.RegisterFilterProvider(); IContainer container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); var resolver = new AutofacWebApiDependencyResolver(container); GlobalConfiguration.Configuration.DependencyResolver = resolver; } }儲存庫:
public interface IRepository<T> { void Add(T entity); void Delete(int id); IEnumerable<T> Find(Expression<Func<T, bool>> filter = null); void Update(int id, T entity); }SharePoint 儲存庫:
internal class SharePointRepository<T> : IRepository<T> where T : IEntity { private readonly ISharePointContext _context; private readonly string _listName; internal SharePointRepository(ISharePointContext context) { _context = context; object[] attributes = typeof (T).GetCustomAttributes(typeof (SharePointListAttribute), false); if (!attributes.Any()) { throw new Exception("No associated SharePoint list defined for " + typeof (T)); } _listName = ((SharePointListAttribute) attributes[0]).ListName; } public void Add(T entity) { throw new NotImplementedException(); } public void Delete(int id) { throw new NotImplementedException(); } public IEnumerable<T> Find(Expression<Func<T, bool>> filter) { throw new NotImplementedException(); } public void Update(int id, T entity) { throw new NotImplementedException(); } }集成控制器:
public class IntegrationController : ApiController { private readonly IRepository<Integration> _repository; public IntegrationController(IRepository<Integration> repository) { _repository = repository; } public void Delete(Guid integrationId) { _repository.Delete(Get(integrationId).Id); } public IEnumerable<Integration> Get() { return _repository.Find(); } public Integration Get(Guid integrationId) { return _repository.Find(i => i.IntegrationId == integrationId).FirstOrDefault(); } public void Post([FromBody] Integration integration) { _repository.Add(integration); } public void Put(Guid integrationId, [FromBody] Integration integration) { _repository.Update(Get(integrationId).Id, integration); } }實體:
internal interface IEntity { int Id { get; } }實體:
public abstract class Entity : IEntity { protected Entity(int id) { Id = id; } public int Id { get; private set; } }一體化:
[SharePointList("Integrations")] public class Integration : Entity { public Integration(int id) : base(id) { } public string ApiUrl { get; set; } public bool DeletionAllowed { get; set; } public Guid IntegrationId { get; set; } public string Key { get; set; } public string List { get; set; } public bool OutgoingAllowed { get; set; } public string RemoteWeb { get; set; } public string Web { get; set; } }
你已經註冊了你的
IRepository錯誤。隨著線:builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();你告訴 Autofac,每當有人要求
IRepository<IEntity>給他們 aSharePointRepository<IEntity>時,你要求的是一個具體的IRepository<Integration>,所以你得到一個例外。您需要的是Autofac 的開放通用註冊功能。因此,將您的註冊更改為:
builder.RegisterGeneric(typeof(SharePointRepository<>)) .As(typeof(IRepository<>));
IRepository<Integration>當您要求 a它會給出 a時,它會像您期望的那樣工作SharePointRepository<Integration>。您還有第二個不相關的問題:您
SharePointRepository只有一個internal建構子。Autofac 預設只查找
public建構子,因此您可以將建構子和類更改為,public或者您需要告訴 Autofac 使用以下FindConstructorsWith方法查找 NonPublic 建構子:builder .RegisterType<SharePointRepository<IEntity>>() .FindConstructorsWith( new DefaultConstructorFinder(type => type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance))) .As<IRepository<IEntity>>();