【问题标题】:Multiple interceptors in NHibernateNHibernate 中的多个拦截器
【发布时间】:2011-08-29 08:59:13
【问题描述】:

我是 NHibernate 的新手,并且一直在关注各种在线教程,尤其是 this one 来创建我自己的程序。我真的很喜欢使用拦截器将INotifyPropertyChanged添加到使用DataBindingFactory创建的实体中,并尝试按照相同的想法将IDataErrorInfo添加到DataBindingFactory使用另一种方法CreateWithValidation(Type type)创建的实体中:

public static object CreateWithValidation(Type type)
{
    return _proxyGenerator.CreateClassProxy(type, new[]
    {
        typeof (IDataErrorInfo),
        typeof (INotifyPropertyChanged)
    }, new IInterceptor[]
    {
        new NotifyPropertyChangedInterceptor(type.FullName),
        new DataErrorInfoInterceptor()
    });
}

NotifyPropertyChangedInterceptor 的代码与链接文章中的代码相同,下面是我对来自this articleDataErrorInfoInterceptor 类的实现:

public class DataErrorInfoInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
        {
            var validator = new ValidatorEngine();
            var errors = validator.Validate(invocation.Proxy);

            if (invocation.Method.Name.Equals("get_Item"))
            {
                String propertyName = Convert.ToString(invocation.Arguments[0]);
                var propertyErrors = errors
                                       .Where(e => e.PropertyName.Equals(propertyName))
                                       .Select(e => e.Message)
                                       .ToArray();

                if (propertyErrors.Count() > 0)
                {
                    invocation.ReturnValue = string.Join(Environment.NewLine, propertyErrors);
                }
                else
                {
                    invocation.ReturnValue = null;
                }
            }
            else if (invocation.Method.Name.Equals("get_Error"))
            {
                var allErrors = errors
                                  .Select(e => e.Message)
                                  .ToArray();

                if (allErrors.Count() > 0)
                {
                    invocation.ReturnValue = string.Join(Environment.NewLine, allErrors);
                }
                else
                {
                    invocation.ReturnValue = null;
                }
            }
            else
            {
                invocation.Proceed();
            }
        }
    }

我遇到的问题是,如果我使用 CreateWithValidation() 方法创建一个对象并在模型上使用它,那么当我离开该字段时,我在视图上的文本框中输入的任何文本都会被清除(这可能也发生在其他领域,但我只在文本框上尝试过)。我怀疑这是因为两个实现IInterceptor 的类都有invocation.Proceed() 行,如果被拦截的方法不是类感兴趣的方法。

我的问题是,是否有可能有两个这样的拦截器,或者我必须有一个大类,例如:CustomInterceptor,它具有所有方法,例如:INotifyPropertyChangedIDataErrorInfo 并处理和他们在一起?这对我来说似乎很笨拙。

不管怎样,这就是我在SessionFactory 上设置拦截器的方式:

public static void Initialise()
{
    Configuration config =  Fluently.Configure()
                                      .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c
                                        .Server("")
                                        .Database("")
                                        .Username("")
                                        .Password("")))
                                      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Map>()
                                        .Conventions.AddFromAssemblyOf<EnumConvention>())
                                      .BuildConfiguration();

    ConfigureNhibernateValidator(config);

    DataBindingInterceptor interceptor = new DataBindingInterceptor();
    SessionFactory = config
                       .SetInterceptor(interceptor)
                       .BuildSessionFactory();

}

【问题讨论】:

    标签: c# nhibernate interceptor


    【解决方案1】:

    问题不在于多个拦截器。问题不在于调用invocation.Proceed()。问题是当方法不是来自IDataErrorInfo 时,您不要在invocation.Proceed() 中调用 invocation.Proceed()(在链接的文章中是正确的)。因此,当您调用某个 getter 或 setter 时,什么都不会发生。

    现在,你有这样的东西:

    if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
    {
        if (invocation.Method.Name.Equals("get_Item"))
        {
            // some code
        }
        else if (invocation.Method.Name.Equals("get_Error"))
        {
            // more code
        }
        else
        {
            invocation.Proceed();
        }
    }
    

    你应该拥有的是:

    if (invocation.Method.DeclaringType.Equals(typeof(IDataErrorInfo)))
    {
        if (invocation.Method.Name.Equals("get_Item"))
        {
            // some code
        }
        else if (invocation.Method.Name.Equals("get_Error"))
        {
            // more code
        }
    }
    else
    {
        invocation.Proceed();
    }
    

    下一次,尝试在调试器中单步调试代码,看看到底发生了什么。

    【讨论】:

    • 非常感谢!我花了整整 20 分钟的时间用调试器逐步完成代码,但我看不出问题出在哪里 - 看不到树木的树木等等!
    猜你喜欢
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多