2013-03-11 33 views
8

私のASP .Net MVC 4プロジェクトでは、AutofacをIoCに使用しています。 Autofacがリポジトリを初期化して、APIコントローラに渡すときに問題があります。AutofacとASP .Net MVC 4 Web API

私の設定には何か不足していると確信しています。ここで

私はに移動したときに私が取得エラーです:

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:ここ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> 

は、関連するいくつかのコードのビットがあります

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

定義「いくつかの問題を抱えて:あなたのどちらかがpublicにあなたのコンストラクタとクラスを変更したり、あなたがFindConstructorsWith方法で非公開のコンストラクタを探しにAutofacに指示する必要がありますので、デフォルトで

Autofacはpublicコンストラクタを探します"これを読んだのですか? http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver –

答えて

9

あなたのIRepository間違って登録されています。ラインで:

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

あなたはいつでも誰かがIRepository<IEntity>は彼らにSharePointRepository<IEntity>を与える要求することAutofacに語っていますが、具体的なIRepository<Integration>を要求しているので、あなたは例外を取得します。

open generic registration feature of Autofacが必要です。あなたはそれがSharePointRepository<Integration>与えるIRepository<Integration>を求めるとき、あなたはあなたの期待通りに動作します

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

:だからに登録を変更します。

SharePointRepositoryにはinternalコンストラクタだけがあります。

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] '型のコンストラクタは、コンストラクタfinder' Autofac.Core.Activators.Reflectionで見つかりません。 DefaultConstructorFinder''を呼び出します。 ここで少し混乱しています。私はすでに 'SharePointContext'を' ISharePointContext'として使うことを定義しています - これはリポジトリが必要とする唯一のパラメータです。 – Moon

+0

問題は、あなたの 'SharePointRepository1'クラスに内部コンストラクタしかないことです。私の更新された答えを見てください。 – nemesv