Problem validating Types with Inheritance

Topics: General discussion, Validation Application Block
Mar 30, 2009 at 3:42 PM

Hi all
I have a baseClass that all my entities inherit from

 

[

Serializable()]
public abstract class BaseData<T> : INotifyPropertyChanging, INotifyPropertyChanged where T : BaseData<T>
{

 

 

               public virtual ValidationResults Validate(T entity, string ruleset)
              {
  
                       IConfigurationSource source = GetValidationConfigSource();
                        Validator<T> validator = ValidationFactory.CreateValidator<T>(ruleset, source);
                       brokenRules = validator.Validate(entity);

 

 

                     return brokenRules;

 

 

 

 

 

 

 

 

             }
}

public class Customer<T> : BaseData<Customer>
{
}

The problem i have is then when I  do thevalidation , "T" validation does not work as it validate based on the baseClass"BaseData" and not on customer and result is always 0.

Public class MyClass
{
   public Customer myCustomer=new Customer();
    public void ValidateCustomer()
   {
         ValidationResults results = myCustomer.Validate(myCustomer, "MyRule");
   }
}

 

Am I missing the obvious?

 

thanks

 

 

 

 

 

 

Mar 31, 2009 at 12:55 PM
Hi,

I can seem to compile you sample codes, it complaining about the Customer<T> generic T in the Customer class, so i removed the <T> and have it compiled successful. Now, As you stated in your problem, As I understand it, you want that the Validation should take place in the Customer Class and not in the BaseData<T> class. I somehow did that by overriding the Validate Method that is defined in the base class. Like this:

 

public class Customer : BaseData<Customer>
{
    [
StringLengthValidator(1,10, MessageTemplate="Must be length 1 to 10.")]
    public string Name { get; set; }
    public override ValidationResults Validate(Customer entity, string ruleset)
    {
        
Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>();
        return validator.Validate(entity);
    }
}


Valiant Dudan
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

Apr 1, 2009 at 5:55 PM
Thanks very much for your reply.
I have created a small noddy project to prove that what I am doing does not validate.
I could have zipped and sent but I dont think is an option in this forum,as it would have made things easier.

Anyway.
my point if you have a 2 level down inheritance it does not work.Not sure if I am doing something wrong or EL cannot cope with it.
What Am i doing wrong?



Your help would really be appreaciated.
Thanks a lot


MyCompany.Core.dll

 

public abstract class BaseData<T> where T: BaseData<T>
{
    private ValidationResults brokenRules;
    public virtual ValidationResults Validate(T entity, string ruleset)
   {
      Validator<T> validator = ValidationFactory.CreateValidator<T>(ruleset);
      brokenRules = validator.Validate(entity);
      return brokenRules;
    }
}

 

MyCompany.Entities.dll

[

Serializable]
public class Person<T>:BaseData<Person<T>>
{
    public string Name { get; set; } 
    public string Surname { get; set; }
}

 

[

Serializable]
public class Customer:Person<Customer>
{
    public string CustomerSpecificProperty { get; set; }
}


WinForm Application

 

 

private void button1_Click(object sender, EventArgs e)

 

{
     //The rule is that you can only have a name with 1-2 letters and surname 1-8

    Customer customer = new Customer{Name ="Jow",Surname ="Blog"};
    
        ValidationResults
results = customer.Validate(customer, "Default");  // it does NOT WORK

 

 

       ValidationResults results2 = Validation.Validate<Customer>(customer, "Default"); //it works

 

 

//Result should be 1 result    Name  validator lowerBound="1" lowerBoundType="Inclusive" upperBound="2"
    

 

 

 

 

}

 


App Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="validation" type="Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationSettings, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </configSections>
    <validation>
        <type defaultRuleset="Default" assemblyName="MyCompany.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            name="MyCompany.Entities.Customer">
            <ruleset name="Default">
                <properties>
                    <property name="Name">
                        <validator lowerBound="1" lowerBoundType="Inclusive" upperBound="2"
                            upperBoundType="Inclusive" negated="false" messageTemplate=""
                            messageTemplateResourceName="" messageTemplateResourceType=""
                            tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null"
                            name="String Length Validator" />
                    </property>
                    <property name="Surname">
                        <validator lowerBound="1" lowerBoundType="Inclusive" upperBound="8"
                            upperBoundType="Inclusive" negated="false" messageTemplate=""
                            messageTemplateResourceName="" messageTemplateResourceType=""
                            tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null"
                            name="String Length Validator" />
                    </property>
                </properties>
            </ruleset>
        </type>
    </validation>
</configuration>

Apr 2, 2009 at 8:11 AM
Hi,

I tried you code snippet and I can see that it is not working as you've described. One thing that I've notice, because I tried to remove the Customer Type in the Validation Application Block in the config, and i tried re adding it, when I try to do a choose members my Visual Studio crashes, do you experience the same? Anyway, I manage to make this inheritance thing work by using the Validation Attributes and not from the config file. With a few code change below. Now, can you please verify that this possible solution works for you also.

 

private ValidationResults brokenRules;
public virtual ValidationResults Validate(T entity) //Removed the Ruleset
{
        Validator<T> validator = ValidationFactory.CreateValidator<T>();
        brokenRules = validator.Validate(entity);
        return brokenRules;
}


Valiant Dudan
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

Apr 2, 2009 at 2:24 PM
Thanks for your reply.
I have used config file as in my real project we use config file and I have never used the attribute.We decided to use config approach .

I dont experience the problem you are having.If helps my solution and the config file   uses "EnterpriseLibraryConfigurationSet=EntLib4Src" for this example.

I have removed the ruleset just to check but i need it anyway but does not work for me.

So why does it work when using

       ValidationResults results2 = Validation.Validate<Customer>(customer, "Default"); //it works

and not when using
       ValidationResults results = customer.Validate(customer, "Default");  // it does NOT WORK

 The idea of being in the baseClass is that you can do  "MyObject.Validate (blah)

Not sure what to do next?
Thanks

 

 

Apr 3, 2009 at 8:08 AM

I'll explain this as clearly as I can.  What really happens inside the Validate method in your BaseData abstract class is when you passed to it an instance of a Customer object, the T or the validator type that it creates is the Person<Customer> type.  You can immediately see this if you tried to override the Validate method from your Customer class.

public override ValidationResults Validate(Person<Customer> entity)
{
}

You can get it to work by replacing your base validation code to:  

public virtual ValidationResults Validate(T entity)
{
    
Validator validator = ValidationFactory
.CreateValidator(entity.GetType());
    
return validator.Validate(entity);
}

I'm not just that sure how this would affect any of your existing logic.



Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

 

 

 

 

 

 


 

 

 

 

 

Apr 3, 2009 at 8:37 AM
thanks a lot for help

It makes perfect sense!!! Silly me i should have thought of that
and works.
I have changed as you suggested.

thanks again for your help