fredag den 4. juli 2014

VB.NET på et website arver ikke altid korrekt (Kontroller)


Hvis du som udvikler arbejder med kontroller, i VB.NET på et website, så kan man lave properties til en KontrolBase som du kan sætte på kontrollen.
Desværre betyder det så bare at den property du har sat ikke er på begge typer objekter - eller værdien er forskellig efter typen.

Hvis du har base-klassen KontrolBase, som har propertien RenderAtHover som kan sættes til en boolean værdi.
Hvis du så har en kontrol der nedarver fra den og sætter den på kontrollen Controls_ContentControls_SectionsImage (som nedarver fra KontrolBase), så hvis du har et andet sted hvor du skal finde den kontrol og typecaste den så er der to scenarier:


  1. Typecaste den til den egentlige type (Controls_ContentControls_SectionsImage)
  2. Typecaste den til base-typen (KontrolBase)
Normalt ville jeg mene at uanset hvilken du satte den til, skulle din property RenderAtHover have samme værdi. Her er VB.NET lidt underlig, for fordi du har sat den på den specialiserede type (Controls_ContentControls_SectionsImage) så skal du typecaste den til denne type for at få værdien.
Hvis du ikke gør det, så er propertien ikke sat.

Dette betyder at når du har nedarvning skal du dermed prøve at lave dit objekt om til de nedarvninger du har for at se hvilke properties der er sat fra hvilke "lag" (nedarvninger). For fx dem som der er sat standard til en default værdi i et tidligere nedarvet lag får du ikke med i det specialiserede når du typecaster med ctype.

Så hvis du på masterpage.master kalder FindControl(SectionsImageID) og får et object tilbage, og typecaster den til KontrolBase så får du ikke værdien sat på den side hvor du bruger kontrollen.

Fx:
AppCode\KontrolBase.vb
Her sætter du Name = "Default name"

Controls\ContentControls\SectionsImage.vb (nedarver fra KontrolBase)
Du sætter Name = "Another name"

Hvis du så på din master har FindControl(SectionsImageID) får du object tilbage.
Derfor må du typecaste.
Hvis du så typecaster den til base-typen mister den sin specialiserede værdi.
dim foundControlObj as object = FindControl(SectionsImageID)
dim specialisedControlBase as KontrolBase = ctype(foundControlObj, KontrolBase)
dim theName as string = specialisedControlBase.Name

theName vil være "Default name", i stedet for "Another name" som den burde være.
Hvis du derimod laver en klasse der hedder SectionsImageBase som du ligger i app_code og nedarver fra denne (som nedarver fra base), så selvom det virker som det samme så bliver det åbenbart ikke fordi du ikke sætter værdien til noget.
Dvs:
AppCode\KontrolBase.vb
Her sætter du Name = "Default name"

AppCode\SectionsImageBase.vb (nedarver fra KontrolBase)
Her sætter du ikke Name til noget default

Controls\ContentControls\SectionsImage.vb (nedarver fra SectionsImageBase)
Her sætter du Name = "Another name"

Dette gør at du kan typecaste din kontrol til en "mere" specialiseret form hvor den ikke default sætter din property til noget. Derfor bliver din property nu "Another name" som den skal.

Ved ikke hvorfor, og kan ikke forklare det. Måske det er fordi den tager scopet af KontrolBase og sætter Name til default name, og fordi "specialiseringen" SectionsImageBase ikke sætter denne property til noget så kan den nu tage den værdi fra den der arver fra den.
Burde ikke være nødvendigt, og er ret sikker på den slags ikke forekommer i C#, men igen som systemudvikler bliver man nogle gange overrasket. Det blev denne C# udvikler i hvert fald!

Ingen kommentarer:

Send en kommentar

Kan du lide mit indlæg, har en kommentar, forslag eller andet på hjerte så skriv venligst