1

我的目标是在我的应用程序中使用Ninject和静态方法。我知道静态方法不应该有任何依赖关系,因为从测试的角度来看它很难。但是,在我的应用程序中,我无法将每个方法从静态变为非静态。我需要以最少的更改来实现 DI,即我应该一次性更改代码,并且应该在调用该方法或类的任何地方更改实现。我也不想使用服务定位器模式,因为它甚至不是纯 DI 模式。

为了牢记以上所有要点,我实施了以下设置,并且运行良好。无论我是否正确使用 Ninject 和静态方法,我都需要你的想法。

我的 ASP.NET WebForms 设置:

解决方案:NinjectPlayGround

项目:

NinjectPlayGround(Web 项目)
NinjectPlayGround.BL(业务层)
NinjectPlayGround.Common(POCO 层)

在此处输入图像描述

为了使用 Ninject,我安装了Ninject.Web

NinjectWebCommon.cs 代码:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectPlayGround.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(NinjectPlayGround.App_Start.NinjectWebCommon), "Stop")]

namespace NinjectPlayGround.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;
    using NinjectPlayGround.Common;
    using NinjectPlayGround.BL;

    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);
                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)
        {
            kernel.Bind<ILogger>().To<DefaultLogger>();

            // Set static properties
            CommonHelper.Logger = kernel.Get<ILogger>();
        }        
    }
}

我在那里添加了以下两条自定义行:

        kernel.Bind<ILogger>().To<DefaultLogger>();

        // Set static properties
        CommonHelper.Logger = kernel.Get<ILogger>();

CommonHelper 是具有静态方法的类,我想在其中使用 Logger 实例。

CommonHelper 类代码:

using NinjectPlayGround.Common;

namespace NinjectPlayGround.BL
{
    public class CommonHelper
    {
        public static ILogger Logger { get; set; }

        public static void RunCleanUp()
        {
            // Run clean up
            //.....


            Logger.Log("Clean up done");
        }
    }
}

ILogger 类代码:

namespace NinjectPlayGround.Common
{
    public interface ILogger
    {
        void Log(string message);
    }
}

DefaultLogger 类代码:

using System.Diagnostics;

namespace NinjectPlayGround.Common
{
    public class DefaultLogger : ILogger
    {
        public void Log(string message)
        {
            Debug.WriteLine(message);
        }
    }
}

由于 Ninject 属性不允许在这样的静态属性上使用:

public static ILogger Logger { get; set; }

我通过NinjectWebCommon类中存在的RegisterServices方法设置该属性,该方法在 每个应用程序启动时仅调用一次(如果我在这里错了,请纠正我)

        // Set static properties
        CommonHelper.Logger = kernel.Get<ILogger>();

在 UI 中,这个辅助方法是这样调用的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ninject;
using NinjectPlayGround.BL;

namespace NinjectPlayGround
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            CommonHelper.RunCleanUp();
        }
    }
}

上述设置工作正常,即如果我将 DefaultLogger 更改为 PersistentLogger(这是 ILogger 的另一种实现)

  kernel.Bind<ILogger>().To<DefaultLogger>();

 kernel.Bind<ILogger>().To<PersistentLogger>(); 

我可以看到 PersistentLogger 被调用而不是 DefaultLogger 而没有在CommonHelper类中进行任何混乱/更改。

这是将 Ninject 与静态方法一起使用的正确方法吗?

这就是我需要在NinjectWebCommon类的RegisterServices方法中设置我需要通过 DI 设置的所有静态属性的方式吗?

我会在这种实施中遇到任何困难吗?

编辑:我已经经历过Ninject 和静态类 - 如何?这是理论上的。我已经询问了在 Ninject 中使用 staic 方法的完整实际实现。此外,这个问题是针对静态类的,在我的案例中,它不是静态类,而是静态方法。

4

0 回答 0