I am very new to NHibernate and have been following various tutorials online, especially this one to create my own program. 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)
:
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:
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). 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.
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? That seems quite unwieldy to me.
For what it's worth, this is how I set the interceptor on my 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<EnumCon开发者_StackOverflow社区vention>())
.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()
. 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). Because of this, when you call some getter or setter, nothing happens.
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.
精彩评论