【发布时间】:2017-08-15 12:59:34
【问题描述】:
我有一个 Web API 解决方案,我想将一个类注入到我的 Controller 构造函数中。
我正在使用统一:
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);
}
}
数据库适配器
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 注入的构造函数,因此对 Update 的调用总是导致 _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
【问题讨论】:
-
The error says no parameterless constructor found.请附上异常的堆栈跟踪/屏幕截图。 -
no parameterless constructor found属于哪一类? -
@ChetanRanpariya - MeasurementsController
-
@ChetanRanpariya - 如果我添加无参数构造函数,我不会收到错误,但 DatabaseAdapter 没有注入并且始终为空。
-
我认为控制器需要一个无参构造函数,尝试从填充实例的无参构造函数中自己调用构造函数。
标签: c# asp.net-mvc asp.net-web-api dependency-injection