C# 如何使用PostSharp AOP获取使用事务属性的当前NHibernate会话?

C# 如何使用PostSharp AOP获取使用事务属性的当前NHibernate会话?,c#,nhibernate,postsharp,C#,Nhibernate,Postsharp,我想使用PostSharp AOP获取当前使用事务属性的NHibernate会话 而不是在下面 public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity { var session = SessionFactory.CurrentSession; using (ITransaction transaction = session.BeginTransaction())

我想使用PostSharp AOP获取当前使用事务属性的NHibernate会话

而不是在下面

public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity
{
    var session = SessionFactory.CurrentSession;

    using (ITransaction transaction = session.BeginTransaction())
    {
        try
    { 
        session.Save(entity);
            transaction.Commit(); 
        } 
        catch {
            transaction.Rollback();
            throw;
        }
    }
}
public void Create(tenty实体),其中tenty:class,IIdentity
{
var session=SessionFactory.CurrentSession;
使用(ITransaction transaction=session.BeginTransaction())
{
尝试
{ 
session.Save(实体);
Commit();
} 
抓住{
transaction.Rollback();
投掷;
}
}
}
我想这样用,

[NHibernateTransaction]
public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity   
{       
    session.Save(entity);
}
[NHibernateTransaction]
public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity   
{       
    session.Save(entity);
}
[NHibernateTransaction]
public void Create(tenty实体),其中tenty:class,IIdentity
{       
session.Save(实体);
}

因为PostSharp方面是基于属性的,所以您无法轻松地将依赖项(例如NHibernate会话)注入其中。您需要依赖环境上下文(静态全局可访问属性/方法)。因此,存储当前会话的位置将根据您正在构建的应用程序类型(ASP、WPF等)而有所不同

我通常使用依赖注入容器(如Castle Windsor)为我提供AOP功能。因为它使用动态拦截而不是IL编织,而且因为方面也从容器中解析,所以您可以轻松地将依赖项注入到它们中。然后,您需要做的唯一一件事就是在容器中注册具有适当生活方式的会话对象(例如web应用程序中的PerWebRequest)

我使用Castle Windsor创建了一个AOP演示。

在PostSharp文档的一节中,您可以找到将依赖项注入方面的不同方法的描述和示例

一种常见的方法是让依赖项注入容器初始化现有方面实例的依赖项。您可以通过aspect的
RuntimeInitialize
方法执行此操作。例如,对于StructureMap容器:

[Serializable]
public class NHibernateTransactionAttribute : OnMethodBoundaryAspect
{
    public ISessionFactory SessionFactory { get; set; }

    public override void RuntimeInitialize(MethodBase method)
    {
        // Initialize the SessionFactory according to the container configuration.
        ObjectFactory.BuildUp(this);
    }

    // ...
}
另一个解决方案是使用DI容器作为方面内的全局服务定位器——只需让容器为您检索所需的实例。作为优化,您可能还希望将
会话
存储在
onetry
方法内的属性中,并在
OnSuccess
oneexception
方法内检索它

public override void OnEntry(MethodExecutionArgs args)
{
    ISessionFactory sessionFactory = ObjectFactory.GetInstance<ISessionFactory>();
    var session = SessionFactory.CurrentSession;
    // Store the session in the method context.
    args.MethodExecutionTag = session;
    // ...
}

public override void OnSuccess(MethodExecutionArgs args)
{
    // Retrieve the session from the method context.
    var session = (ISession) args.MethodExecutionTag;
    // ...
}

谢谢你的快速回复。 AlexD你的第二个建议对我很有帮助,但除了以下几点补充

在NHibernateTransactionAttribute类中,我这样做了

[Serializable]
public sealed class NHibernateTransactionAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect
{
    [ImportMember("Session", IsRequired = true)] 
    public Property<ISession> SessionProperty;

    public override void OnEntry(MethodExecutionArgs args)
    {
        var session = this.SessionProperty.Get();
        session.Transaction.Begin();
    }

    public override void OnSuccess(MethodExecutionArgs args)
    {
        var session = this.SessionProperty.Get();
        session.Transaction.Commit();
    }

    public override void OnException(MethodExecutionArgs args)
    {
        var session = this.SessionProperty.Get();
        session.Transaction.Rollback();
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        var session = this.SessionProperty.Get();
        session.Close();
    }

    public object CreateInstance(AdviceArgs adviceArgs)
    {
        return this.MemberwiseClone();
    }

    public void RuntimeInitializeInstance()
    {
    }
}
[IntroduceMember(Visibility = Visibility.Family, OverrideAction = MemberOverrideAction.Ignore)]
[CopyCustomAttributes(typeof (ImportAttribute))]
[Import(typeof(ISession))]
public ISession Session
{
  get
  {
    if(session == null || !session.IsOpen)
    {
       session = sessionFactory.OpenSession();
    }
   return session;
  }
}
我现在可以在事务方面获得当前的NHibernate会话,我可以像这样使用Create

[NHibernateTransaction]
public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity   
{       
    session.Save(entity);
}
[NHibernateTransaction]
public void Create<TEntity>(TEntity entity) where TEntity : class, IIdentity   
{       
    session.Save(entity);
}
[NHibernateTransaction]
public void Create(tenty实体),其中tenty:class,IIdentity
{       
session.Save(实体);
}