Несколько перехватчиков в NHibernate - PullRequest
1 голос
/ 28 августа 2011

Я очень новичок в NHibernate и следую различным учебным пособиям онлайн, особенно этому , чтобы создать свою собственную программу. Мне очень понравилось использование перехватчика для добавления 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 такой же, как в связанной статье, и ниже моя реализация класса 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();
            }
        }
    }

Проблема, с которой я сталкиваюсь, заключается в том, что если я создаю объект с использованием метода CreateWithValidation() и использую его на модели, любой текст, который я ввожу в текстовое поле в представлении, очищается, когда я убираю вкладку из поля (возможно бывает и в других областях, но я пробовал это только на текстовых полях). Я подозреваю, что это связано с тем, что оба класса, реализующие IInterceptor, имеют строку invocation.Proceed(), если перехваченный метод не тот, который интересует класс.

У меня вопрос: возможно ли иметь два перехватчика, подобных этому, или мне нужен один массивный класс, например: CustomInterceptor, который имеет все методы, например: INotifyPropertyChanged и IDataErrorInfo и с ними там? Это кажется мне довольно громоздким.

Для чего это стоит, вот как я установил перехватчик на моем 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();

}

1 Ответ

3 голосов
/ 29 августа 2011

Проблема не в нескольких перехватчиках.И проблема не в том, чтобы звонить invocation.Proceed().Проблема в том, что вы не вызываете invocation.Proceed() в вашем DataErrorInfoInterceptor, когда метод не из IDataErrorInfo (это правильно в связанной статье).Из-за этого, когда вы вызываете какой-нибудь метод получения или установки, ничего не происходит.

Прямо сейчас у вас есть что-то вроде этого:

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

В следующий раз попробуйте пройтись по коду в отладчике, чтобы увидеть, что на самом деле происходит.

...