[英]Property injection failing with both Ninject and Simple Injector
更新-事實證明這是配置錯誤/代碼錯誤的地方。 現在工作了。
我已經掃描了其他SO條目(有些條目確實很舊),但找不到答案。 我正在嘗試遵循亞當·弗里曼(Adam Freeman)的書“ Pro ASP.NET MVC 5”中提供的示例(是的,雖然有些陳舊,但仍然不錯),並且在該示例中,他使用Ninject。
在適應當前的Web技術(我使用的是.NET Framework 4.7)之后,我按照示例進行了操作,更新了基本項目(該項目開始時是一個空的MVC,同時選中了Mvc和WebApi),並且一切正常,直到注入一個屬性示例。
我對自己想,“好吧,Ninject的牙齒長了一點,我不認為它已經得到維護,所以我將嘗試一個新的小工具,我聽說它是Really Fast-SimpleInjector”。
創建了一個全新的項目,僅跨(復制)了示例類,並以推薦的方式設置了SI。 同樣的問題!
你問什么問題? 很簡單,我希望注入創建的具體類中的值不會被注入。
要復制(或至少遵循),您需要創建一個標准的ASP.NET MVC應用程序(非域,在Windows 10 Creator環境中為Visual Studio 2017,Enterprise,15.3.4,.NET Framework版本4.7),選擇“空”,然后選中“ MVC和Web API”復選框。 本書的內容還不盡如人意,但我需要一個無關緊要的項目。 同樣,遵循本書中列出的示例,DI以及全部都可以正常使用,並且Ninject可以達到屬性注入點。
從那時起,我添加了一個簡單的類來支持購物卡,一個計算總成本的小工具和一個應用折扣的小工具。 真的很簡單的東西。 以下是使用每個DI容器為每個模型制作的mod:
Ninject:在NinjectWebCommon.cs文件中,RegisterServices方法:
kernel.Bind<IDiscountHelper>()
.To<DiscountHelper>()
.WithPropertyValue(nameof(DiscountHelper.DiscountSize), 15.0M);
kernel.Bind<ILinqValueCalculator>().To<LinqValueCalculator>();
kernel.Bind<IShoppingCart>().To<ShoppingCart>();
在SimpleInjector中(創建了一個單獨的類來執行“注冊”:
// Put all the aContainer.Register<ISomeInterface, SomeConcreteClass>(LifetimeScope) calls here
aContainer.Register<IDiscountHelper, DiscountHelper>(new AsyncScopedLifestyle());
// How to inject a property initializer
aContainer.RegisterInitializer<IDiscountHelper>
(
i =>
{
i.DiscountSize = 15M;
i.DiscountAmount = 30M;
}
);
aContainer.Register<ILinqValueCalculator, LinqValueCalculator>(new AsyncScopedLifestyle());
aContainer.Register<IShoppingCart, ShoppingCart>(new AsyncScopedLifestyle());
該視圖采用一個非常簡單的模型,只是一個具有兩個屬性的類,兩個屬性均為十進制,一個具有原始總計,一個具有折現總計。 盡管將折扣金額設置為至少1500萬,但兩個數字相同。 如果我刪除屬性注入並在各個位置硬編碼一個值,則數字會正確顯示。 簡而言之,在兩個DI容器中注入均失敗。 事實並非如此,我無法弄清為什么會這樣。
非常感謝您的協助。 如果需要更多代碼,請發表評論,然后將整個項目上載為.zip。
答案是要確保所有正確的初始化都以正確的順序進行。 還需要確保引用了正確的IDependencyResolver版本(有兩個版本,另一個版本運行不佳)。 為我為Ninject解決它的代碼是這樣的(感謝生成了SO條目的書的作者Adam Freeman):
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.WebApi;
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using Web.Models;
[ assembly:WebActivatorEx.PreApplicationStartMethod(typeof(Web.App_Start.NinjectWebCommon), "Start")]
[ assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(Web.App_Start.NinjectWebCommon), "Stop")]
namespace Web.App_Start {
public static class NinjectWebCommon {
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start() {
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop() {
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel() {
var kernel = new StandardKernel();
try {
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver =
new NinjectDependencyResolver(kernel);
return kernel;
} catch {
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel) {
System.Web.Mvc.DependencyResolver.SetResolver(new
MvcNinjectDependencyResolver(kernel));
}
}
public class MvcNinjectDependencyResolver : IDependencyResolver {
private IKernel kernel;
public MvcNinjectDependencyResolver(IKernel kernelParam) {
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType) {
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType) {
return kernel.GetAll(serviceType);
}
private void AddBindings() {
kernel.Bind<IDiscountHelper>()
.To<DiscountHelper>()
.WithPropertyValue(nameof(DiscountHelper.DiscountSize), 15.0M);
kernel.Bind<ILinqValueCalculator>().To<LinqValueCalculator>();
kernel.Bind<IShoppingCart>().To<ShoppingCart>();
}
}
}
和SimpleInjector解決方案:
using Web;
using WebActivator;
[assembly: PostApplicationStartMethod(typeof(SimpleInjectorWebInitializer), nameof(SimpleInjectorWebInitializer.Initialize))]
namespace Web
{
using System.Reflection;
using System.Web.Http;
using System.Web.Mvc;
using Infrastructure;
using SimpleInjector;
using SimpleInjector.Integration.Web;
using SimpleInjector.Integration.Web.Mvc;
using SimpleInjector.Integration.WebApi;
public static class SimpleInjectorWebInitializer
{
/// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary>
public static void Initialize()
{
var vContainer = new Container();
// To use the "greediest constructor" paradigm, add the following line:
vContainer.Options.ConstructorResolutionBehavior =
new MostResolvableParametersConstructorResolutionBehavior(vContainer);
vContainer.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
InitializeContainer(vContainer);
// From the docs, these next two lines need to be added for MVC
vContainer.RegisterMvcControllers(Assembly.GetExecutingAssembly());
vContainer.RegisterMvcIntegratedFilterProvider();
// This is for Web Api
vContainer.RegisterWebApiControllers(GlobalConfiguration.Configuration);
vContainer.Verify();
// This is needed for MVC
DependencyResolver.SetResolver
(new SimpleInjectorDependencyResolver(vContainer));
// This is needed for WebApi
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(vContainer);
}
private static void InitializeContainer(Container aContainer)
{
// This is just a call to a regular static method of a static class
// that performs the container.Register calls.
InitializeContainerBindings.InitializeBindings(aContainer);
}
}
}
兩家公司都將開始創建一個MVC 5項目,該項目將在同一項目中同時支持MVC和WebApi。 我正在研究的案例是一個簡單的示例,但至少是一個開始,而不是一個錯誤。 感謝所有人(尤其是亞當·弗里曼)的支持。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.