簡體   English   中英

Ninject和Simple Injector都無法進行屬性注入

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM