简体   繁体   English

NHibernate中的多个拦截器

[英]Multiple interceptors in NHibernate

I am very new to NHibernate and have been following various tutorials online, especially this one to create my own program. 我对NHibernate还是很陌生,并且一直在网上关注各种教程,尤其是用这一教程来创建自己的程序。 I really liked the use of the interceptor to add INotifyPropertyChanged to entities created using the DataBindingFactory and tried to follow the same idea to add IDataErrorInfo to entities created by the DataBindingFactory with another method CreateWithValidation(Type type) : 我真的很喜欢使用拦截器将INotifyPropertyChanged添加到使用DataBindingFactory创建的实体中,并尝试遵循相同的想法通过另一个方法CreateWithValidation(Type type)IDataErrorInfo添加到由DataBindingFactory创建的实体中:

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

The code for the NotifyPropertyChangedInterceptor is the same as in the linked article and below is my implementation of the DataErrorInfoInterceptor class which came from this article : 对于代码NotifyPropertyChangedInterceptor相同链接的文章中和下面是我实现的DataErrorInfoInterceptor这些来自一流的这篇文章

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();
            }
        }
    }

The problem that I have is that if I create an object using the CreateWithValidation() method and use it on a model, any text I enter into a textbox on the view is cleared when I tab away from the field (this probably happens in other fields as well but I've only tried it on textboxes). 我遇到的问题是,如果我使用CreateWithValidation()方法创建一个对象并在模型上使用它,那么当我离开该字段时,输入到视图上文本框中的任何文本都会被清除(这可能会在其他情况下发生)字段,但我只在文本框上尝试过)。 I suspect that this is because both of the classes implementing IInterceptor have the line invocation.Proceed() if the method that has been intercepted is not one that the class is interested in. 我怀疑这是因为如果已拦截的方法不是该类感兴趣的方法,则两个实现IInterceptor的类都具有invocation.Proceed()行。

My question is, is it possible to have two interceptors like this or do I have to have one massive class, eg: CustomInterceptor which has all of the methods for, eg: INotifyPropertyChanged and IDataErrorInfo and deal with them there? 我的问题是,是否可能有两个这样的拦截器,或者我是否必须有一个大型类,例如: CustomInterceptor ,它具有所有方法,例如: INotifyPropertyChangedIDataErrorInfo并在那里处理? That seems quite unwieldy to me. 对我来说,这似乎很笨拙。

For what it's worth, this is how I set the interceptor on my SessionFactory : 对于它的价值,这就是我在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();

}

The problem is not multiple interceptors. 问题不在于多个拦截器。 And the problem is not calling invocation.Proceed() . 问题不在于调用invocation.Proceed() The problem is that you don't call invocation.Proceed() in your DataErrorInfoInterceptor when the method is not from IDataErrorInfo (it's correct in the linked article). 问题是,当方法不是来自IDataErrorInfo时,您不会DataErrorInfoInterceptor 调用 invocation.Proceed() (在链接的文章中是正确的)。 Because of this, when you call some getter or setter, nothing happens. 因此,当您调用某个getter或setter时,什么也不会发生。

Right now, you have something like this: 现在,您会看到以下内容:

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();
    }
}

What you should have is this: 您应该拥有的是:

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();
}

Next time, try stepping through the code in debugger to see what's really going on. 下次,尝试逐步调试程序中的代码以查看实际情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM