1

我已經呆了好幾天了,但是我無法讓Unity向Controller注入任何與RegisterType<>的東西。我在Visual Studio 2015中使用Web Api 2和Unity 4.無論何時我嘗試注入IUnitOfWorkIRFContext,我都會得到"message": "An error occurred when trying to create a controller of type 'ClPlayersController'. Make sure that the controller has a parameterless public constructor."。 我使用Unity.AspNet.WebApi來引導進入WebApi。下面是我UnityWebApiActivator無法使用Unity將DBContext注入到我的Web API 2控制器中

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

我使用Start.cs中由於Owin。

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

如果我的控制器是這樣的,它工作正常:

public class ClPlayersController : ApiController 
{ 
    private readonly IMapper mapper; 

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

但將IUnitOfWork,如下圖所示,或IRFContext,我得到的錯誤:

private readonly IMapper mapper; 
    private readonly IUnitOfWork unitOfWork; 

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

我找不到,對於生活的我,我做錯了什麼。如果我通過構造函數上的container.Registrations循環,我找到映射,但它們拒絕被注入。任何提示?

EDIT

下面是的UnitOfWork和RFContext

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

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

和RFContext代碼是一個基本的POCO產生的DbContext

namespace mycompany.project.data.configuracao 
{ 
    using System.Linq; 

    public class RFContext : System.Data.Entity.DbContext, IRFContext 
    { 
     public System.Data.Entity.DbSet<ClGrupoEconomico> ClGrupoEconomicoes { get; set; } 
       //all my DbSets 
     public System.Data.Entity.DbSet<SpTipoLog> SpTipoLogs { get; set; } 

     static RFContext() 
     { 
      System.Data.Entity.Database.SetInitializer<RFContext>(null); 
     } 

     public RFContext() 
      : base("Name=RFContext") 
     { 
     } 

     public RFContext(string connectionString) 
      : base(connectionString) 
     { 
     } 

     public RFContext(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model) 
      : base(connectionString, model) 
     { 
     } 

     public RFContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection) 
      : base(existingConnection, contextOwnsConnection) 
     { 
     } 

     public RFContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection) 
      : base(existingConnection, model, contextOwnsConnection) 
     { 
     } 

     protected override void Dispose(bool disposing) 
     { 
      base.Dispose(disposing); 
     } 

     protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 

      modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration()); 
         //all my Configuration classes 
      modelBuilder.Configurations.Add(new SpTipoLogConfiguration()); 
     } 

     public static System.Data.Entity.DbModelBuilder CreateModel(System.Data.Entity.DbModelBuilder modelBuilder, string schema) 
     { 
      modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration(schema)); 
         //all my configuration classes 
      modelBuilder.Configurations.Add(new SpTipoLogConfiguration(schema)); 
      return modelBuilder; 
     } 
    } 
} 
+0

你可以分享你的'UnitOfWork'和'RFContext'的代碼嗎? – smoksnes

回答

2

不幸的是,您看到的異常可能會出於以下幾個原因。其中之一是當Unity無法解決一個或多個注射。

An error occurred when trying to create a controller of type 'FooController'. Make sure that the controller has a parameterless public constructor.

因此,基於在你的問題中的信息您的設置顯然是正確的,因爲IMapper可以注射。因此我猜UnitOfWorkRFContext有依賴Unity無法解決。也許一個存儲庫?

UPDATE:

這裏的問題是,你的RFContext有幾個構造函數。

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

When a target class contains more than one constructor with the same number of parameters, you must apply the InjectionConstructor attribute to the constructor that the Unity container will use to indicate which constructor the container should use. As with automatic constructor injection, you can specify the constructor parameters as a concrete type, or you can specify an interface or base class for which the Unity container contains a registered mapping.

在這種情況下,團結不知道如何解決您的RFContext,並會嘗試使用構造最參數。你可以通過使用

container.RegisterType<IRFContext, RFContext>(new InjectionConstructor()); 
+0

我已經添加了代碼。 RFContext只是一個基本的POCO生成的DBContext,而UnitOfWork加載它。我認爲是有關這個問題:http://stackoverflow.com/questions/30397188/unable-to-inject-with-unity-a-complex-type-to-web-api-2。但是,我無法確定我在註冊順序上做了什麼錯誤。任何與RegisterType不起作用。非常感謝您的幫助。 – Pascal

+0

我已經更新了我的答案。 – smoksnes

+0

你是我的英雄!有效。我如何與PerThreadLifetimeManager一起使用InjectionConstructor?非常感謝! – Pascal

相關問題