0

明らかに、私は何かが欠けています。MVC アプリケーションがあり、Ninject 3 と MVC3 拡張機能をインストールしました (ただし、MVC4 を実行しています)。SiteSettingsプロジェクト全体で参照されるクラスがあります。これは次のようになります。

public class SiteSettings
{
    private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();
    private static ObservableDictionary<string, string> settings;
    private static bool Initialized = false;
    private static DataPersister persister;

    public static void Initialize()
    {
        if (Initialized) throw new InvalidOperationException("The SiteSettings object has already been initialized.");
        persister = new DataPersister();
        using (var u = persister.UnitOfWorkFactory.GetUnitOfWork())
        {
            var settingsList = u.SiteSettings.GetAll();
            settings = new ObservableDictionary<string, string>(settingsList.ToDictionary(key => key.SiteSettingName, value => value.SiteSettingValue));
            settings.OnChange += new kvpChangeEvent<string, string>(settings_OnChange);
        }
        Initialized = true;
    }

    static void settings_OnChange(object sender, odKVPChangeEventArgs<string, string> e)
    {
        using (var u = persister.UnitOfWorkFactory.GetUnitOfWork())
        {
            var setting = u.SiteSettings.GetByName(e.Key);
            setting.SiteSettingValue = e.Value;
            u.SiteSettings.Update(setting);
            u.Save();
            Logger.Info(i => i("Changed the '{0}' site setting from '{1}' to '{2}'.", e.Key, e.OldValue, e.Value));
        }
    }

    private static int _ItemsPerPage;
    public static int ItemsPerPage
    {
        get
        {
            return _ItemsPerPage;
        }
        set
        {
            _ItemsPerPage = value;
            settings["itemsPerPage"] = value.ToString();
        }
    }

    private static int _SessionLifeInMinutes;
    public static int SessionLifeInMinutes
    {
        get
        {
            return _SessionLifeInMinutes;
        }
        set
        {
            _SessionLifeInMinutes = value;
            settings["sessionLifeInMinutes"] = value.ToString();
        }
    }

    private static string _DateFormat;
    public static string DateFormat
    {
        get
        {
            return _DateFormat;
        }
        set
        {
            _DateFormat = value;
            settings["defaultDateFormat"] = value;
        }
    }
}

次のようにデータ永続化オブジェクトを作成しました。

public class DataPersister
{
    public IUnitOfWorkFactory UnitOfWorkFactory { get; set; }
}

...そして、私はNinjectWebCommon.csこのように見えます:

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();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IUnitOfWork>().To<NHUnitOfWork>();
        kernel.Bind<IUnitOfWorkFactory>().To<NHUnitOfWorkFactory>();
    }
}

依存性注入のすべての要件を満たしているように思えます。私Global.asax.cs Application_Start()はこのように見えます:

protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new MonoRazorViewEngine());

    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    ControllerBuilder.Current.DefaultNamespaces.Add("MyApplication.Application.Controllers");
    Initialize.Security();
    SiteSettings.Initialize();
}

...それでも、必要なデータを収集しようとすると、SiteSettingsクラスには常に null があります。IUnitOfWorkFactory

私は何を間違っていますか?すべての例がそうであるべきだと示唆しているように見えますが、私は愛されていません.

アップデート

Bassam Mehanni のアドバイスを使用して、DataPersisterクラスを次のように書き直しました。

public class DataPersister
{
    private IUnitOfWorkFactory UnitOfWorkFactory;
    public DataPersister(IUnitOfWorkFactory unitOfWorkFactory)
    {
        UnitOfWorkFactory = unitOfWorkFactory;
    }
    public IUnitOfWork GetUnitOfWork()
    {
        return UnitOfWorkFactory.GetUnitOfWork();
    }
}

...しかしもちろん、私のSiteSettingsクラスは私のパラメーターなしのコンストラクターについて不平を言っています。それについて私は何をすべきですか?

更新 2

続けて、DataPersisterクラスを次のように書き直しました。

public class DataPersister
{
    private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();

    private IUnitOfWorkFactory UnitOfWorkFactory { get; set; }
    public IUnitOfWork GetUnitOfWork()
    {
        return UnitOfWorkFactory.GetUnitOfWork();
    }
    [Inject]
    public DataPersister(IUnitOfWorkFactory factory)
    {
        Logger.Info("Injected constructor called");
        UnitOfWorkFactory = factory;
    }
    public DataPersister()
    {
        Logger.Info("Parameterless constructor called");
    }
}

SiteSettings次に、クラスを次のように書き直しました。

public class SiteSettings
{
    private static readonly Common.Logging.ILog Logger = Common.Logging.LogManager.GetCurrentClassLogger();
    private ObservableDictionary<string, string> settings;
    private DataPersister persister;
    private SiteSettings()
    {
        persister = new DataPersister();
        using (var u = persister.GetUnitOfWork())
        {
            var settingsList = u.SiteSettings.GetAll();
            settings = new ObservableDictionary<string, string>(settingsList.ToDictionary(key => key.SiteSettingName, value => value.SiteSettingValue));
            settings.OnChange += new kvpChangeEvent<string, string>(settings_OnChange);
        }
    }
    private static SiteSettings instance;

    public static SiteSettings Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new SiteSettings();
            }
            return instance;
        }
    }

    private void settings_OnChange(object sender, odKVPChangeEventArgs<string, string> e)
    {
        using (var u = persister.GetUnitOfWork())
        {
            var setting = u.SiteSettings.GetByName(e.Key);
            setting.SiteSettingValue = e.Value;
            u.SiteSettings.Update(setting);
            u.Save();
            Logger.Info(i => i("Changed the '{0}' site setting from '{1}' to '{2}'.", e.Key, e.OldValue, e.Value));
        }
    }

    private int _ItemsPerPage;
    public int ItemsPerPage
    {
        get
        {
            return _ItemsPerPage;
        }
        set
        {
            _ItemsPerPage = value;
            settings["itemsPerPage"] = value.ToString();
        }
    }

    private int _SessionLifeInMinutes;
    public int SessionLifeInMinutes
    {
        get
        {
            return _SessionLifeInMinutes;
        }
        set
        {
            _SessionLifeInMinutes = value;
            settings["sessionLifeInMinutes"] = value.ToString();
        }
    }

    private string _DateFormat;
    public string DateFormat
    {
        get
        {
            return _DateFormat;
        }
        set
        {
            _DateFormat = value;
            settings["defaultDateFormat"] = value;
        }
    }
}

これはうまくいかないのですか?そうではないからです。クラスはDataPersister常にパラメーターなしのコンストラクターで呼び出されます。私のカーネルバインディングは次のようになります:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IUnitOfWork>().To<NHUnitOfWork>();
    kernel.Bind<IUnitOfWorkFactory>().To<NHUnitOfWorkFactory>();
}

私が見逃しているものは他にありますか?これは非常にイライラしています。

4

2 に答える 2

3

静的クラスなしに依存する静的クラスは、IoCコンテナーを使用するときに実行すべきではないことです。代わりに、ライフタイムがシングルトンのnone静的クラスを作成する必要があります。

  1. SiteSettingsクラスを静的にしないでください。
  2. コンストラクタインジェクションを使用して、IUnitOfWorkFactoryなどのすべての依存関係をSiteSettingsに注入します
  3. SiteSettingsのシングルトンスコープでバインディングを作成します
  4. unsingコンストラクタインジェクションにアクセスする必要がある場合は、SiteSettingsのインスタンスを取得します。

例:

public class SiteSettings {
    public SiteSettings(IUnitOfWorkFactory uowFactory) { .... }

    ....
}


public class INeedToAccessSiteSettings
{
    public INeedToAccessSiteSettings(SiteSettings siteSettings) { .... }
}

kenrel.Bind<SiteSettings>().ToSelf().InSingletonScope();
于 2013-01-18T11:56:44.770 に答える
3

通常、ninject はサービスをコンストラクターなどに注入します。実行時にすべてのインターフェイスを魔法のようにオブジェクト インスタンスに変換するわけではありません。

例えば:

public class MyController : Controller
{
   private IServiceThatINeed _serviceThatINeed;
   public MyController(IServiceThatINeed serviceThatINeed)
   { 
       _serviceThatINeed = _serviceThatINeed;
   }
}

この場合、カーネル インスタンスを登録したので、mvc はこの依存関係を解決する方法を知っており、実装するオブジェクトのインスタンスを渡しますIServiceThatINeed(この依存関係を解決する方法を ninject に指示したと仮定します。

ここで、mvc フレームワークによってコンストラクターに注入されずにサービスを取得する必要があるインスタンスがあるかもしれません。これらのインスタンス (ここにあるものなど) では、使用する必要があります。ServiceLocator

例えば:

var myService = ServiceLocator.Current.GetInstance<IServiceThatINeed>()

を使用するにはServiceLocator、への参照を追加する必要がありますMicrosoft.Practices.ServiceLocation

それが役立つことを願っています!

于 2013-01-17T23:45:37.410 に答える