Enterprise Library 3.1: Validation Block (3. daļa)

Šī ir trešā sadaļa par Microsoft Enterprise Library 3.1 pārbaudes un validācijas bloku. Šajā rakstā mēs apskatīsim ET pārbaudes bloka plašākas iespējas, t.i., nosacījumu kopas un iebūvētos (angl. out-of-the-box) pārbaudītājus.

Konfigurācijas avoti

Nepieciešamās pārbaudes sistēmā ir iespējams nodefinēt vairākos veidos:
-        Ar koda atribūtu palīdzību (nepieciešamās pārbaudes tiek definētas un kompilētas kodā)
-        Ar konfigurācijas avotu palīdzību (konfigurācija ir izdalīta no sistēmas koda un ir viegli modificējama sistēmas ražošanas stadijā)
-        Ar abu iepriekšminēto paņēmienu kombināciju
-        Ir iespējams definēt pašvalidējošus (angl. self-validation) objektus, kuriem „iekšienē” ir definēta pārbaude, kas nosaka, vai objekts ir „pareizs” vai nav

Ārējā konfigurācijas faila piegājiens ir elastīgāks ar to, ka nepieciešamās izmaiņas pārbaudes blokā ir iespējams veikt arī nepārkompilējot sistēmas izejas kodu, t.i., mainīt pārbaudes bloka uzstādījumus tieši sistēmas ražošanas laikā (angl. production). Tomēr šai stratēģijai ir negatīvā puse – pārbaudīt vai nav pieļautas gramatiskas kļūdas ir iespējams tikai izpildes laikā – turpretim atribūtu pieeja dod garantiju par pareizumu, jo tiek definēti tieši izejas kodā.

Ir iespējami 2 veidi konfigurācijas avoti:
-        Informācija atrodas tieši aplikācijas konfigurācijas failā
-        Informācija atrodas atsevišķā ārējā konfigurācijas failā

Lai definētu, ka pārbaudes bloka konfigurācija atrodas atsevišķā failā aplikācijas konfigurācijas failā ir jānorāda ceļš uz failu.

<configuration>
  <
configSections>
    <
section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null" />
  </
configSections>
  <
enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source">
    <
sources>
      <
add name="File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null"
        filePath="..\ValidationConfiguration.config" />
    </
sources>
  </
enterpriseLibrary.ConfigurationSource>
</
configuration>


Pārbaudes bloka uzstādījumi nav nekas vairāk par Xml dokumentu, kurā ir aprakstīta visa informācija, ko ir iespējams uzstādīt ar atribūtiem.

<configuration>
  <
configSections>
    <
section name="validation" type="Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationSettings, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </
configSections>
  <
validation>
    <
type assemblyName="ValidationQuickStart.BusinessEntities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
      name="ValidationQuickStart.BusinessEntities.Address">
      <
ruleset name="Rule Set">
        <
properties>
          <
property name="City">
            <
validator lowerBound="1" lowerBoundType="Inclusive" upperBound="30"
              upperBoundType="Inclusive" negated="false" messageTemplate=""
              messageTemplateResourceName="" messageTemplateResourceType=""
              tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
              name="String Length Validator" />
            <
validator characterSet="1234567890!@#$%^&amp;amp;*()-=" containsCharacter="Any"
              negated="false" messageTemplate="City may not contain numbers or punctuation characters"
              messageTemplateResourceName="" messageTemplateResourceType=""
              tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.ContainsCharactersValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
              name="Contains Characters Validator" />
            <
validator negated="false" messageTemplate="" messageTemplateResourceName=""
              messageTemplateResourceType="" tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
              name="Not Null Validator" />
          </
property>
        </
properties>
      </
ruleset>
    </
type>
    ...
  </
validation>
</
configuration>


Jāpiemin gan, ka lielos projektos, kur pārbaudāmo objektu skaits pārsniedz vismaz 10 ir noteikti ieteicams konfigurācijas avotus sadalīt vēl pa atsevišķiem failiem, jo šis konfigurācijas fails nav ļoti pārskatāms. ET nāk līdzi konfigurācijas faila reaktors, kas atvieglo darbu izmaiņu veikšanai.



No sistēmas koda viedokļa nekādas izmaiņas nav jāveic, ja sistēma savu pārbaudes bloka konfigurācija grib saņemt no ārēja faila. Visu darbu paveic aplikācijas konfigurācijas faila ieraksts, kurš sistēmai paziņo pārbaudes bloka konfigurācijas faila atrašanās vietu (Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource).

Nosacījumu kopas

ET 3.1 piedāvā iespēju apvienot noteiktus nosacījumus kopās. Šīs kopas dod iespēju vienkopus apvienot nosacījumus, kas attiecas uz kādu konkrētu gadījumu vai scenāriju.

[DateTimeRangeValidator("2007-10-27T00:00:00", "2008-10-27T00:00:00", Ruleset="StandardCustomer")]
[DateTimeRangeValidator("2007-10-27T00:00:00", "2010-10-27T00:00:00", Ruleset="GoldCustomer")]
public DateTime MembershipExpirationDate;

Augstāk redzamais koda piemērs definē klienta piederības laika periodu, ļaujot klientiem, kas pieder „GoldCustomer” grupai, ilgāku laiku būt noteiktas grupas dalībniekiem.
Lai pārbaudītu objektu pēc noteiktas pārbaužu kopas, ir pareizi jākonstruē
Validator<Customer> objekts.

Validator<Customer> validatorGoldCustomer =
    ValidationFactory.CreateValidator<Customer> ("GoldCustomer");

ValidationResults resultsGoldCustomer = validatorGoldCustomer.Validate (customer);

Jāpiemin tikai, ka jābūt ir uzmanīgiem ar kopu nosaukumiem un to pielietojumiem (atsaucēm), jo veidojot jaunu pārbaužu kopu ar atribūtu vai ārējā konfigurācijas faila palīdzību netiek pārbaudīts kopas nosaukuma pareizums, t.i., ja gramatiski būs kļūdas kopas nosaukumos, tiks izveidotas vairākas pārbaužu kopas.

Biežāk lietotie iebūvētie pārbaudītāji

ET nāk kopā jau ar noteiktu skaitu iebūvētu pārbaudītāju. Šajā sadaļā apskatīsim tikai dažus no tiem. Detalizētu informāciju par katru no pārbaudes mehānismiem var iegūt ET dokumentācijā.Biežāk lietotie pārbaudītāji:
-        NotNullValidator: dod iespēju pārbaudīt vai mērķis nav tukšs, t.i., null;
-        StringLengthValidator: dod iespēju pārbaudīt vai mērķis atbilst konkrēta teksta garuma robežās. Pārsvarā izmanto, lai objekta vērtības nepārsniegtu, piemēram, datubāzes kolonu atļautos garumus;
-        RelativeDateTimeValidator: dod iespēju pārbaudīt vai mērķis atbilst noteiktam datuma intervālam relatīvi norādot pieļaujamās apakšējās un augšējās robežas vērtības;
-        RegexValidator: dod iespēju veikt regulāro izteiksmju pārbaudi uz mērķa;
-        ObjectValidator: dod iespēju pārbaudīt attiecīgo tipu. Šo pārbaudītāju pielieto koka veida struktūru tipa objektos, kad jāpārbauda ir objekta reference;
-        ContainsCharactersValidator: dod iespēju pārbaudīt vai mērķis satur konkrētu teksta vērtību;
-        PropertyComparisonValidator: dod iespēju mērķi pārbaudīt pret kādu citu vērtību (angl. property) no objekta. Šim pārbaudītājam ir iespējams arī norādīt operāciju kādā veidā notiks salīdzināšana (vienāds, lielāks, mazāks, utt);

Pieejamajos iebūvētajos pārbaudītājos eksistē vēl divas speciālie pārbaudītāji, kas apvieno citus pārbaudītājus loģiskajās operācijas:
-        ValidatorComposition(CompositionType.And): dod iespēju apvienot visus pārbaudītājus ar loģisko UN operāciju. Jāpiemin, ka ET noklusētā apvienošana ir loģiskais UN, tāpēc šis pārbaudes kompozīciju veidojošais elements būtu jāizmanto tikai sarežģītu uzbūvju konstruēšanā;
-        ValidatorComposition(CompositionType.Or): dod iespēju apvienot visus pārbaudītājus ar loģisko VAI operāciju, kas nozīmē, ka mērķis ir „pareizs”, ja vismaz viens no pārbaudītājiem izpildās sekmīgi;

Globalizācija

Jautājums varētu rasties sakarā ar globalizāciju pārbaudes rezultātiem, kā attēlot pārbaudes rezultātus dažādās valodās?
Šim nolūkam kalpo pārbaudītāju divi uzstādījumi (parametri):
-        MessageTemplateResourceType: norāda, kādā tipā glabājas resursi;
-        MessageTemplateResourceName: norāda resursa nosaukumu;

Jāpiemin, ka pašreiz ET pārbaudes bloks atbalsta tikai uz Resx failiem bāzētos resursu piegādātājus, bet ir iespējams arī paplašināt ET pārbaudes bloku pašam, pievienojot nepieciešamo resursa iegādes mehānismu pašam.

Tātad projektam pievienojam Resx failus ar resursiem un to vērtībām:




Pārbaudām vai resursi ir iekompilēti korekti:



Globalizācijas apskates laikā saskāros ar vienu interesantu problēmu, kuru apskatīsim zemāk.
Tātad, loģiski būtu, ja klienta kods izskatītos kaut kas līdzīgs šim:

Customer customer = new Customer();
customer.Name = "very long customer name";

Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>();
ValidationResults results = validator.Validate(customer);

Thread.CurrentThread.CurrentUICulture = new CultureInfo("lv-LV");
foreach (ValidationResult result in results)
{
    Console.WriteLine (result.Message);
}

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
foreach (ValidationResult result in results)
{
    Console.WriteLine(result.Message);
}

Augstāk redzamais koda piemērs izveido jaunu klienta klases instanci, piešķir klientam vārdu un pārbauda klienta objektu pret norādītajām kodā pārbaudēm, kā arī pārbaužu rezultātus attēlo dažādās valodās. Tomēr šis piemērs neizpildās sekmīgi:




Kā redzams, tad pavediena (angl. thread) kultūras maiņa neietekmē pārbaudes rezultāta attēlošanu.
Nākamais, kas ienāca prātā, bija varbūt ir vērts izveidot jaunu pārbaudītāju (
Validator<Customer>).

Thread.CurrentThread.CurrentUICulture = new CultureInfo("lv-LV");
Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>();
ValidationResults results = validator.Validate(customer);
foreach (ValidationResult result in results)
{
    Console.WriteLine (result.Message);
}

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Validator<Customer> validatorUS = ValidationFactory.CreateValidator<Customer>();
ValidationResults resultsUS = validatorUS.Validate(customer);
foreach (ValidationResult result in resultsUS)
{
    Console.WriteLine(result.Message);
}

Rezultāts no šīm izmaiņām nemainījās un palika tāds pats.



Pētot izejas kodu ET validācijas blokam, atklājās, ka Validator objekti tiek uzturēti atmiņā (angl. caching). Un zemāk redzamajam kodam nav nozīmes kāda ir pašreizējā pavediena kultūra.

Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>();

Nav nozīmēs tāpēc, ka izveides brīdī, tiek izveidoti arī visi attiecīgie pārbaudītāji, kas ir definēti konkrētajam objektam (šajā gadījumā
Customer). Izveides brīdī, katrs no pārbaudītājiem saņem MessageTemplate vērtību, kas tiek nolasīta no attiecīgā resursa tipa un nosaukuma, kā arī izveides laikā pašreizējā pavediena kultūras vērtības. Tas nozīmē, ka atkārtota Validator<Customer> objekta izveide „zem citas kultūras„ nedos nekādu efektu, jo tāpat tiks lietots iepriekš izveidotais objekts, kas tiks paņemts no atmiņas.
Izpētot izejas kodu vienīgā iespēja, kā tika panākta daudzvalodība, ir veidot
Validator<Customer> objektu no jauna norādot noklusēto konfigurācijas avotu:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Validator<Customer> validatorUS = ValidationFactory.CreateValidator<Customer>(new SystemConfigurationSource());
ValidationResults resultsUS = validatorUS.Validate(customer);

foreach (ValidationResult result in resultsUS)
{
    Console.WriteLine(result.Message);
}

Kā redzams no izpildes rezultātiem, tad vēlamais efekts tiek panākts, tikai tas prasa papildus pārbaudi vēlreiz konkrētajam mērķim.



Ļoti iespējams, ka dinamiska resursi meklēšana izpildes laikā netika iestrādāta domājot par ET pārbaudes bloka ātrdarbības rādītājiem, kaut gan pārbaudīt objektu vēlreiz ar savādāk izveidotu Validator<Customer> objektu man liekas neefektīvāks salīdzinot ar ET pārbaudes bloka modifikāciju, lai resursi tiktu meklēti izpildes laikā J.

Nākamajā un noslēdzošajā ET pārbaudes bloka aprakstā mēs apskatīsim integrāciju Windows Forms aplikācijās kā arī apskatīsim bloka integrācijas iespējas WCF (Windows Communication Foundation) sistēmās.

Published Wednesday, September 05, 2007 12:53 PM by valdis.iljuconoks

Comments

# Interesting, thanks

I really like it when folks arrive collectively and share opinions, excellent weblog, hold it up.

Wednesday, November 16, 2011 11:39 PM by Refugio Ator

Leave a Comment

(obligāts) 
(obligāts) 
(brīvizvēles)
(obligāts)