2013-03-11 104 views
8

我正在使用Autofac在我的ASP.Net MVC 4項目中使用IoC。 Autofac在初始化存儲庫並將其傳遞給API控制器時遇到了一些問題。Autofac和ASP .Net MVC 4 Web API

我相信我錯過了我的配置中的東西。

這裏是我的錯誤,當我瀏覽到: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; 
    } 
} 

IRepository:

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); 
} 

SharePointRepository:

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(); 
    } 
} 

IntegrationController:

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); 
    } 
} 

IEntity:

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; } 
} 
+0

定義「遇到了一些麻煩」。你讀過這個了嗎? http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver – 2013-03-11 18:20:25

回答

9

您註冊IRepository錯誤。隨着行:

builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>(); 

你告訴Autofac,每當有人會請求IRepository<IEntity>給他們一個SharePointRepository<IEntity>,但您請求的具體IRepository<Integration>,所以你得到一個異常。

你需要的是open generic registration feature of Autofac。因此,改變你的登記:

builder.RegisterGeneric(typeof(SharePointRepository<>)) 
     .As(typeof(IRepository<>)); 

它將工作如你所願,當你問一個IRepository<Integration>它會給一個SharePointRepository<Integration>

您還有第二個不相關的問題:您的SharePointRepository只有一個internal構造函數。

Autofac默認只查找public構造函數,所以你要麼改變你的構造函數和類public或者你需要告訴Autofac尋找非公開構造與FindConstructorsWith方法:

builder 
    .RegisterType<SharePointRepository<IEntity>>() 
    .FindConstructorsWith(
     new DefaultConstructorFinder(type => 
      type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance))) 
    .As<IRepository<IEntity>>(); 
+0

這確實幫助我解決了我最初遇到的問題。但是,現在我得到一個新的錯誤:'沒有類型爲'EL.Web.Infrastructure.SharePointRepository'1 [EL.Web.Models.Integration]'的構造函數可以通過構造函數查找器'Autofac.Core.Activators.Reflection'找到。 DefaultConstructorFinder''。 我在這裏有點困惑。我已經定義使用'SharePointContext'作爲'ISharePointContext' - 這是存儲庫需要的唯一參數。 – Moon 2013-03-12 05:00:33

+0

你的問題是你的'SharePointRepository1'類只有內部構造函數。看到我更新的答案。 – nemesv 2013-03-12 05:56:31