【问题标题】:Ninject ignoring [Inject] attributeNinject 忽略 [Inject] 属性
【发布时间】:2011-07-19 04:55:06
【问题描述】:

我有一个像这样的 Ninject 和 NHibernate 设置。现在,如果我有这种情况..

class HomeController : Controller
{
 [Inject]
 public ISession Session { get; set; }

}

这可以正常工作。

但是如果我再上一堂课……

class QueryObject
{
 [Inject]
 public ISession Session { get; set; }
}

// .. somewhere else in my program.
var test = new QueryObject().Execute();

ISession 为空!这不仅适用于 ISession,而且适用于我尝试注入的任何内容。

这是我的 SessionModule:

public class SessionModule : Ninject.Modules.NinjectModule
{
    private static ISessionFactory sessionFactory;

    public override void Load()
    {
        Bind<ISessionFactory>()
            .ToMethod(c => CreateSessionFactory())
            .InSingletonScope();

        Bind<ISession>()
            .ToMethod(c => OpenSession())
            .InRequestScope()
            .OnActivation(session =>
            {
                session.BeginTransaction();
                session.FlushMode = FlushMode.Commit;
            })
            .OnDeactivation(session =>
            {
                if (session.Transaction.IsActive)
                {
                    try
                    {
                        session.Transaction.Commit();
                    }
                    catch
                    {
                        session.Transaction.Rollback();
                    }
                }
            });
    }

    /// <summary>
    /// Create a new <see cref="NHibernate.ISessionFactory"/> to connect to a database.
    /// </summary>
    /// <returns>
    /// A constructed and mapped <see cref="NHibernate.ISessionFactory"/>.
    /// </returns>
    private static ISessionFactory CreateSessionFactory()
    {
        if (sessionFactory == null)
            sessionFactory = Persistence.SessionFactory.Map
                (System.Web.Configuration
                    .WebConfigurationManager
                    .ConnectionStrings["Local"]
                    .ConnectionString
                );
        return sessionFactory;
    }

    /// <summary>
    /// Open a new <see cref="NHibernate.ISession"/> from a <see cref="NHibernate.ISessionFactory"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="NHibernate.ISession"/>.
    /// </returns>
    private static ISession OpenSession()
    {
        // check to see if we even have a session factory to get a session from
        if (sessionFactory == null)
            CreateSessionFactory();

        // open a new session from the factory if there is no current one
        return sessionFactory.OpenSession();
    }
}

【问题讨论】:

  • NB 一般而言,查询对象(与一般实体一样)首先不应该有这样的依赖关系

标签: ninject


【解决方案1】:

如果您想自己创建对象,可以执行以下操作:

class QueryObject
{
  [Inject]
  public ISession Session { get; set; }
}

// .. somewhere else in my program.
var test = new QueryObject();
kernel.Inject(test);

然后,Ninject 将尝试满足您的依赖关系。

【讨论】:

  • 另外,对于属性和 Inject 属性需要注意的一点,如果属性是私有的,Ninject 无法进行绑定。
  • 不是 100% 正确的。默认情况下,它不会为私人注入,但您可以在 ninject 设置中启用它
【解决方案2】:

它适用于控制器,因为您使用 Ninject 实例化它们(通过控制器工厂)。

当您使用new QueryObject().Execute(); 时,您并没有使用 Ninject 来实例化您的 QueryObject。 .NET 框架本身不知道注入属性。

您需要使用 Ninject Kernel 来解析您的 QueryObject。应该这样做:

IKernel kernel = new StandardKernel(new SessionModule());
var queryObject = kernel.Get<QueryObject>();
queryObject.Execute();

然后内核将实例化一个新的 QueryObject 并正确设置所有依赖项。

为此,您必须注册 QueryObject:

Bind<QueryObject>().ToSelf();

这告诉 Ninject 在您执行 kernel.Get&lt;QueryObject&gt;(); 时始终返回一个 QueryObject 实例

这是在您的SessionModule 中完成的。

我建议阅读文档中的Modules and the Kernel。 ≈

【讨论】:

  • 有没有办法设计一个非服务定位器模式让 Ninject 在其注入中包含标记为 IInject 的东西?
  • 是的,确保从一开始就使用 Ninject 实例化所有内容。您在哪里使用 QueryObject?
  • 还没有。在我开始用它做任何事情之前,我试图看看我是否能让它工作。我试图通过封装查询和命令以获得性能粒度来设计总线服务/消息处理程序系统而不是存储库模式。不幸的是,如果我必须依赖服务定位器模式,这将不起作用。而且我已经阅读了整个 Ninject 文档,并没有真正逃避这一点。
  • 这里应该不需要服务定位器。只要您确保 Ninject 实例化您的依赖项。我建议使用构造函数注入。如果您能够显示一些代码,则更容易提供帮助。
  • 谢谢。我想我不能用 Ninject 做我想做的事。我将不得不考虑一种不同的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-11
相关资源
最近更新 更多