Castle Active Record (Linq AND Validation) Problem
I am trying out Castle ActiveRecord. I want to use the Validation features AND the LINQ features.
In order to use LINQ, you can either:
- My preference: Make your entities inherit from - ActiveRecordLinqBase<T>, then to query:- var blogs = (from b in Blog.Queryable select b).ToList(); 
- Use - ActiveRecordLinq.AsQueryable<T>, e.g.:- var blogs = (from b in ActiveRecordLinq.AsQueryable() select b).ToList() 
Now, to  use the validation features, you have to make your entities inherit from ActiveRecordValidationBase<T>.
Multiple inheritance isn't supported so, here's my options:
- Use #2 from above while making my entities inherit from ActiveRecordValidationBase<T>. Disadvantage: LINQ statements are longer and uglier.
- Create a class that inherits from ActiveRecordLinqBase<T>and duplicates the code found inActiveRecordValidationBase<T>. Disadvantage: Duplicate code, which must be updated with future ActiveRecord releases. Here's the class:
Edit: 3. (Not Tested) Simulate multiple inheritance. Disadvantage: Have to keep Property and Method Definitions in sync with updates.
using System;
using System.Collections;
using System.Xml.Serialization;
using Castle.ActiveRecord.Framework;
using Castle.Components.Validator;
using NHibernate.Type;
namespace Castle.ActiveRecord.Linq
{
    [Serializable]
    public abstract class ActiveRecordValidationLinqBase<T> : ActiveRecordLinqBase<T>, IValidationProvider where T : class
    {
        // Fields
        [NonSerialized]
        private IValidationProvider _actualValidator;
        // Methods
        protected ActiveRecordValidationLinqBase() { }
        protected override bool BeforeSave(IDictionary state)
        {
            if (!this.IsValid(RunWhen.Insert))
            {
                this.OnNotValid();
            }
            return base.BeforeSave(state);
        }
        public virtual bool IsValid()
        {
            return this.ActualValidator.IsValid();
        }
        public virtual bool IsValid(RunWhen runWhen)
        {
            return this.ActualValidator.IsValid(runWhen);
        }
        protected override bool OnFlushDirty(object id, IDictionary previousState, IDictionary currentState, IType[] types)
        {
            if (!this.IsValid(RunWhen.Update))
            {
                this.OnNotValid();
            }
            return base.OnFlushDirty(id, previousState, currentState, types);
        }
        protected virtual void OnNotValid()
        {
            ActiveRecordValidator.ThrowNotValidException(this.ValidationErrorMessages, this.PropertiesValidationErrorMessages);
        }
        // Properties
        [XmlIgnore]
        protected virtual IValidationProvider ActualValidator
        {
            get
            {
                if (this._actualValidator == null)
                {
                    this._actualValidator = new ActiveRecordValidator(this);
                }
                return this._actualValidator;
            }
        }
        [XmlIgnore]
        public virtual IDictionary PropertiesValidationErrorMessages
        {
            get
            {
                return this.ActualValidator.PropertiesValidationErrorMessages;
            }
        }
        public开发者_C百科 virtual string[] ValidationErrorMessages
        {
            get
            {
                return this.ActualValidator.ValidationErrorMessages;
            }
        }
    }
}
Is there a better way?
to use the validation features, you have to make your entities inherit from ActiveRecordValidationBase.
Not necessarily. Validation is a separate Castle project, it's not very tightly coupled to ActiveRecord. You can run the validation manually. By manually I mean wrapping this in your own repository/DAO class.
And since it's loosely coupled you could even choose any other validation framework.
Personally, I don't consider ActiveRecordLinq<Blog>.AsQueryable() to be much longer or uglier than Blog.Queryable so I'd go with that option.
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论