10

我在我的 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; }
}
4

1 回答 1

10

你已经注册了你的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>>();
于 2013-03-11T19:12:34.103 回答