Autofac和ASP .Net MVC 4 Web API

10

我在我的ASP .Net MVC 4项目中使用Autofac进行IoC。Autofac在初始化存储库并将其传递给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; }
}

定义“遇到一些麻烦”。你读过这个吗?http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver - Erik Funkenbusch
1个回答

10

您注册了IRepository错误。使用以下代码行:

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

你告诉Autofac,每当有人请求一个IRepository<IEntity>时,给他们一个SharePointRepository<IEntity>,但你请求的是一个具体的IRepository<Integration>,所以你会收到一个异常。

你需要的是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>>();

这确实帮助我解决了最初遇到的问题。但是现在我又遇到了一个新错误:在类型“EL.Web.Infrastructure.SharePointRepository1[EL.Web.Models.Integration]”上找不到使用构造函数查找器“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”的构造函数`。我有点困惑。我已经定义要使用 SharePointContext 作为 ISharePointContext,而这是存储库所需的唯一参数。 - Moon
дҪ зҡ„й—®йўҳжҳҜSharePointRepository1зұ»еҸӘжңүеҶ…йғЁжһ„йҖ еҮҪж•°гҖӮиҜ·еҸӮиҖғжҲ‘зҡ„жӣҙж–°зӯ”жЎҲгҖӮ - nemesv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接