无法使用Unity将DBContext注入我的Web API 2控制器

时间:2016-08-12 00:02:27

标签: entity-framework asp.net-web-api dependency-injection asp.net-web-api2 unity-container

我已经好几天了,但我无法让Unity向<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ca.osmcanada</groupId> <artifactId>OSVUploadr</artifactId> <version>0.1-ALPHA</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>com.github.scribejava</groupId> <artifactId>scribejava-apis</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.9.1</version> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifest> <mainClass>ca.osmcanada.osvuploadr.JFMain</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <mainClass>ca.osmcanada.osvuploadr.JFMain</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> </execution> </executions> </configuration> </plugin> </plugins> </build> </project> 注入RegisterType<>的任何内容。我在Visual Studio 2015中使用Web Api 2和Unity 4.每当我尝试注入ControllerIUnitOfWork时,我都会IRFContext。 我正在使用"message": "An error occurred when trying to create a controller of type 'ClPlayersController'. Make sure that the controller has a parameterless public constructor."来引导WebApi。以下是我的Unity.AspNet.WebApi

UnityWebApiActivator

由于Owin,我正在使用Start.cs。

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Shutdown")]

namespace mycompany.project.api
{
    public static class UnityWebApiActivator
    {
        public static void Start() 
        {
            var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
            GlobalConfiguration.Configuration.DependencyResolver = resolver;
        }

        public static void Shutdown()
        {
            var container = UnityConfig.GetConfiguredContainer();
            container.Dispose();
        }
    }
}

我的[assembly: OwinStartup(typeof(mycompany.project.api.Startup))] namespace mycompany.project.api { public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); ConfigureOAuth(app); config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer()); WebApiConfig.Register(config); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); app.UseWebApi(config); } public void ConfigureOAuth(IAppBuilder app) { OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() { AllowInsecureHttp = true, TokenEndpointPath = new PathString("/token"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), Provider = new SimpleAuthorizationServerProvider(), RefreshTokenProvider = new SimpleRefreshTokenProvider() }; // Token Generation app.UseOAuthAuthorizationServer(OAuthServerOptions); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } } } 位于以下位置:

WebApiConfig.cs

我的namespace mycompany.project.api { public static class WebApiConfig { public static void Register(HttpConfiguration config) { log4net.Config.XmlConfigurator.Configure(); config.MapHttpAttributeRoutes(); config.EnableSystemDiagnosticsTracing(); config.Services.Add(typeof(IExceptionLogger), new SimpleExceptionLogger(new LogManagerAdapter())); config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); } } } 位于

之下
UnityConfig.cs

namespace mycompany.project.api { public class UnityConfig { #region Unity Container private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => { var container = new UnityContainer(); RegisterTypes(container); return container; }); public static IUnityContainer GetConfiguredContainer() { return container.Value; } #endregion public static void RegisterTypes(IUnityContainer container) { var config = new MapperConfiguration(cfg => { //AutoMapper bindings }); container.RegisterInstance<IMapper>(config.CreateMapper()); container.RegisterType<IRFContext, RFContext>(new PerThreadLifetimeManager()); container.RegisterType<IUnitOfWork, UnitOfWork>(); XmlConfigurator.Configure(); var logManager = new LogManagerAdapter(); container.RegisterInstance<ILogManager>(logManager); } } } 中的所有内容都在下面:

Global.asax

如果我的控制器是这样的,它可以正常工作:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Error()
    {
        var exception = Server.GetLastError();
        if (exception != null)
        {
            var log = new LogManagerAdapter().GetLog(typeof(WebApiApplication));
            log.Error("Unhandled exception.", exception);
        }
    }
}

但放置IUnitOfWork,如下所示,或IRFContext,我收到错误:

public class ClPlayersController : ApiController
{
    private readonly IMapper mapper;

    public ClPlayersController(IMapper _mapper, IUnityContainer container)
    {
        mapper = _mapper;
    }

对于我的生活,我找不到我做错了什么。如果我遍历构造函数上的 private readonly IMapper mapper; private readonly IUnitOfWork unitOfWork; public ClPlayersController(IMapper _mapper, IUnityContainer container, IUnitOfWork _unitOfWork) { mapper = _mapper; unitOfWork = _unitOfWork; } ,我会找到映射,但是它们拒绝注入。任何提示?

修改

以下是UnitOfWork和RFContext的代码

container.Registrations

namespace mycompany.project.data.configuracao
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly IRFContext _rfContext;
        private bool _disposed = false;

        public UnitOfWork(IRFContext rfContext)
        {
            _rfContext = rfContext;
        }
        public void Commit()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            _rfContext.SaveChanges();
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing && _rfContext != null)
            {
                _rfContext.Dispose();
            }

            _disposed = true;
        }
    }
}

和RFContext是一个基本的POCO生成的DBContext

namespace mycompany.project.data.configuracao
{
    public interface IUnitOfWork : IDisposable
    {
        void Commit();
    }
}

1 个答案:

答案 0 :(得分:2)

不幸的是,您看到的异常可能由于多种原因而发生。其中之一是当Unity无法解决您的一次或多次注射时。

  

尝试创建类型的控制器时发生错误   &#39; FooController的&#39 ;.确保控制器具有无参数   公共建设者。

因此,根据您问题中的信息,您的设置显然是正确的,因为可以注入IMapper。因此,我猜测 UnitOfWorkRFContext具有Unity无法解析的依赖关系。也许是一个存储库?

<强>更新

这里的问题是你的RFContext有几个构造函数。

https://msdn.microsoft.com/en-us/library/cc440940.aspx#cnstrctinj_multiple

  

当目标类包含多个具有相同构造函数的构造函数时   参数个数,您必须应用InjectionConstructor   属性为Unity容器将用于的构造函数   指示容器应该使用哪个构造函数。和自动一样   构造函数注入,可以将构造函数参数指定为   具体类型,或者您可以为其指定接口或基类   Unity容器包含已注册的映射。

在这种情况下,Unity并不知道如何解析RFContext,并会尝试使用具有最多参数的构造函数。您可以使用

解决它
container.RegisterType<IRFContext, RFContext>(new InjectionConstructor());