Estendere una proprietà di un controllo

venerdì 15 novembre 2013 - 17.22
Tag Elenco Tags  C#  |  .NET 3.5  |  .NET 4.0  |  Windows 7  |  Visual Studio 2010

andrestu Profilo | Expert

Salve a tutti,
vorrei capire se cè il modo per estendere una proprietà di un WebControl senza però creare una classe derivata, diciamo un pò come usare un ExtensionMethod però applicato alle proprietà.
Il "problema" si presenta in questo contesto, ammettiamo di avere la seguente struttura:
(scusate gli errori di sintassi, scrivo a mano per farvi capire)

public class MyTextbox : TextBox { ... }
public class MyButton : Button{ ... }

a questo punto amettiamo che volessi estendere i miei due controlli personalizzati con la stessa proprietà, l'unica soluzione sarebbe replicare per ogni classe la nuova proprietà, capite che se però i controlli personalizzati sono diversi e poi si vuole in futuro cambiare la logica relativa a queste proprietà bisogna intervenire su ogni singolo controllo, cè qualche soluzione in merito da adottare per creare un design con una logica migliore ?
sul sito di Microsoft ho trovato questo:
http://msdn.microsoft.com/en-us/library/vstudio/ms171836.aspx
però l'articolo è riferito a windows form e a quanto ho capito l'implementazione in Aspnet è differente, ho trovato pochissimi esempi in rete e devo dire la verità che non ci ho capito molto, avete mai usato un Extender Provider per risolvere questa problematica?

Andrea Restucci - Web Developer

0v3rCl0ck Profilo | Guru

Ciao, nel tuo caso si presta bene l'applicazione del design pattern "Decorator", perchè quando estendi un controllo consumi già l'unico slot di ereditarietà che hai a disposizione, e per questo motivo devi trovare un alternativa all'ereditarietà ed esistono dei pattern che risolvono questi casi come appunto il decorator:

http://www.dofactory.com/Patterns/PatternDecorator.aspx

il tuo sarebbe un decorator di un System.Web.UI.Control, che è alla base di tutti i controlli asp.net, così il tuo decorator, sarebbe in grado di decorare qualsiasi controllo web, aggiungendo appunto le proprietà che necessiti.


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

andrestu Profilo | Expert

mmm forse non sono riuscito ad interpretare bene il concetto esposto da questo partner ma non credo che mi risolva il problema.
prendendo l'esempio dei book e video e comparandolo alla realtà dei controlli aspnet si potrebbe pensare che le due classi book e video corrispondono a due controlli (esempio textbox e button) a questo punto se volessi creare una proprietà che sia accessibile da ogni istanza dei due oggetti dovrei fare:

textbox myControl1 = new textbox();
button myControl2 = new button();
Borrowable borrowvideo = new Borrowable(myControl1);
...

cioè secondo l'esempio sono obbligato ad istanziare un terzo oggetto (Borrowable) il che mi complicherebbe di non poco la stesura del codice ed andrei incontro ad un altra problematica, le proprietà in comune devono essere viste dal design di Aspnet (costruzione della pagina .aspx) in questo modo non credo proprio che vengono lette e assegnate...
quello che mi servirebbe è questo:

(una classe o del codice comune in cui inserisco proprietà e metodi comuni)
public class ESEMPIO
{
public string MyCommonProperty { get; set; }
}

textbox myControl1 = new textbox();
button myControl2 = new button();

myControl1.MyCommonProperty ...
myControl2.MyCommonProperty ...






Andrea Restucci - Web Developer

0v3rCl0ck Profilo | Guru

Che io sappia il design di asp.net vede solo le proprietà pubbliche esposte dal controllo stesso con una serie di attributi che devono essere definiti, quindi non credo riuscirai ad evitare di cambiare il tipo di oggetto istanziato, quello che credo invece si possa ottenere sia incapsulare in una classe i comportamenti che vuoi aggiungere, e applicare l'estensione ai vari componenti, potendo così scrivere una sola volta l'implementazione dell'estensione.

EDIT: il decorator a pensarci bene non fa al caso tuo, perchè quando crei la classe decorator deve essere conforme ad un interfaccia, e nel tuo caso vorrebbe dire che dovresti fare un decoratore per ogni componente (textbox, button) e poi potere aggiungere tante più estensioni che vuoi, ma invece tu vuoi creare un estensione in comune, che appunto in altri progetti (winforms e wpf) è stato risolto con gli extender/attached properties che in asp.net non hai.


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

Puoi disegnare qualcosa di simile all'extender provider:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

e poi usarlo nel code-behind, ma comunque non nel designer:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

non prendere questa come una buona implementazione, ma solo un esempio di quello che si può fare, devi lavorarci su, per capire che chiave utilizzare, perchè utilizzare semplicemente il riferimento all'oggetto come winforms/wpf fa, non funzionerebbe in asp.net, perchè ogni volta che la pagina viene chiamata gli oggetti vengono ricreati, per questo ho ricavato la chiave dal tipo di pagina, il tipo di controllo e l'id del componente.

Se questo esempio potrebbe fare al caso tuo, potresti poi creare un motore di estensione più generico, che ti dia la possibilità di registrare più estensioni sullo stesso controllo. Wpf implementa un GetValue e SetValue direttamente su ogni controllo, in questo modo il tracking delle attached property è legato al ciclo di vita del componente stesso, quando muore, con esso muoiono tutte le registrazioni. Nel tuo caso questi GetValue e SetValue, dovrebbero essere gestiti a parte in una classe che viene istanziata all'inizio dell'applicazione e che tenga traccia di tutte le estensioni aggiunte per ogni controllo. Il punto più difficile è il tracking di queste attached property, quando le crei? quando le distruggi? ecc... Per ora l'implementazione che ti ho dato le tiene per tutta la durata dell'applicazione e uguale per ogni utente connesso, divise per pagina, quindi da qui devi capire come personalizzare la cosa per salvare i dati nella viewstate, piuttosto che in sessione o comunque divisi anche per session_id.

Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5