2017-08-15 58 views
1

我有一個Web API解決方案,我想將一個類注入到Controller的構造函數中。Web API,Unity和無參數構造函數

我使用統一:

WebApiConfig.cs

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     var container = new UnityContainer(); 
     container.RegisterType<IDatabaseAdapter, DatabaseAdapter>(new HierarchicalLifetimeManager()); 
     config.DependencyResolver = new UnityResolver(container); 

     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 
     var constraintResolver = new DefaultInlineConstraintResolver 
           { 
            ConstraintMap = 
            { 
             ["apiVersion"] = typeof(ApiVersionRouteConstraint) 
            } 
           }; 
     config.MapHttpAttributeRoutes(constraintResolver); 
     config.AddApiVersioning(); 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 
    } 
} 

UnityResolver

public class UnityResolver : IDependencyResolver 
{ 
    protected IUnityContainer _container; 

    public UnityResolver(IUnityContainer container) 
    { 
     _container = container ?? throw new ArgumentNullException("container"); 
    } 

    public object GetService(Type serviceType) 
    { 
     try 
     { 
      return _container.Resolve(serviceType); 
     } 
     catch (ResolutionFailedException) 
     { 
      return null; 
     } 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     try 
     { 
      return _container.ResolveAll(serviceType); 
     } 
     catch (ResolutionFailedException) 
     { 
      return new List<object>(); 
     } 
    } 

    public IDependencyScope BeginScope() 
    { 
     var child = _container.CreateChildContainer(); 
     return new UnityResolver(child); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     _container.Dispose(); 
    } 
} 

我的控制器。

[System.Web.Http.RoutePrefix("api/v{version:apiVersion}/measurements")] 
[ApiVersion("1.0")] 
public class MeasurementsController : Controller 
{ 
    private readonly IDatabaseAdapter _databaseAdapter; 
    [InjectionConstructor] 
    public MeasurementsController(IDatabaseAdapter databaseAdapter) 
    { 
     _databaseAdapter = databaseAdapter; 
    } 
    [MapToApiVersion("1.0")] 
    [System.Web.Http.Route("GetTrafficLights")] 
    public JsonResult GetTrafficLights() 
    { 
     var trafficLights = TrafficLightCache.TrafficLightCache.TrafficLights(); 
     var result = new JsonResult 
     { 
      Data = JsonConvert.SerializeObject(trafficLights), 
      JsonRequestBehavior = JsonRequestBehavior.AllowGet 
     }; 
     return result; 
    } 
    [MapToApiVersion("1.0")] 
    [System.Web.Http.Route("UpdateMeasurement")] 
    public async Task<HttpStatusCodeResult> Update(string measurementToUpdate) 
    { 
     var measurement = JsonConvert.DeserializeObject<Measurement>(measurementToUpdate, new JsonSerializerSettings 
     { 
      DateTimeZoneHandling = DateTimeZoneHandling.Utc 
     }); 
     await _databaseAdapter.Update(measurement); 
     return new HttpStatusCodeResult(HttpStatusCode.Accepted); 
    } 
} 

DatabaseAdapter

public class DatabaseAdapter : IDatabaseAdapter 
{ 
    public async Task<Dictionary<int, CacheEntry>> MeasurementCache() 
    { ... } 

    public async Task Update(Measurement measurement) 
    { ... } 
} 

IDatabaseAdapter

public interface IDatabaseAdapter 
{ 
    Task<Dictionary<int, TrafficLightCache.CacheEntry>> MeasurementCache(); 
    Task Update(Measurement measurement); 
} 

錯誤說,沒有參數的構造函數中。如果我添加一個空的無參數構造函數,它永遠不會激發包含IDatabaseAdapter注入的構造函數,因此對「始終更新」的調用總是導致_databaseAdapter爲空。

堆棧跟蹤爲

[MissingMethodException: No parameterless constructor defined for this object.] 
    System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 
    System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +119 
    System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +247 
    System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 
    System.Activator.CreateInstance(Type type) +11 
    System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55 

[InvalidOperationException: An error occurred when trying to create a controller of type 'APITest2.Controllers.V1.MeasurementsController'. Make sure that the controller has a parameterless public constructor.] 
    System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178 
    System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76 
    System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88 
    System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +194 
    System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50 
    System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48 
    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 
+0

'錯誤說沒有找到無參數的構造函數.'請包括一個例外的堆棧跟蹤/截圖。 – mjwills

+0

'無參數構造函數找到哪個類? –

+0

@ChetanRanpariya - MeasurementsController – Stuart

回答

2

您需要用戶ApiController。不是控制器。