Asp.net-Mvc-4

Autofac 和 ASP .Net MVC 4 Web API

  • October 5, 2017

我在我的 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>>();

引用自:https://stackoverflow.com/questions/15345462