Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[C#] Dynamische members toevoegen

Pagina: 1
Acties:

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 22-10 10:28
Ik ben bezig met een applicatie die records uit een database leest. Opzich geen probleem, maar klanten mogen zelf columns toevoegen aan tables. Nu wil ik deze columns natuurlijk kunnen uitlezen en kunnen assignen aan properties.

Voorbeeld:
Aan de tabel Products voegt een klant de column ProductSize toe.

Deze wil ik kunnen gebruiken als een propertie maar die zal ik dynamisch in me code moeten aanmaken. Is dit mogelijk? Ik heb op google een en ander gezocht maar kwam niet echt verder. Wat ik eigenlijk wil is dat het volgende dynamisch word opgebouwd:

code:
1
2
3
4
5
public int ProductSize
{
   get {return productSize;}
   set { productSize= value; }
}


Kan iemand me een duw in de goede richting geven? :)

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 21:39

mulder

ik spuug op het trottoir

Ik zou niet proberen dynamisch properties te gaan maken. Kijk eens naar een NameValueCollection.

oogjes open, snaveltjes dicht


  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Je zou eventueel dynamisch het object kunnen aanmaken (Microsoft.CSharp.CSharp.CSharpCodeProvider) en deze later via reflection kunnen uitlezen, maar echt handig is dat niet.

Een oplossing kan zijn om de extra velden in een XML document te defineren (XML db type):
XML:
1
2
3
4
<fields>
  <field name="Length" type="number">43</field>
  <field name="Pages" type="number">250</field>
</fields>


Je zou ook een een Hashtable kunnen gebruiken en deze de inhoud via (de)serialisatie kunnen verwerken.

If it isn't broken, fix it until it is..


  • L-VIS
  • Registratie: April 2005
  • Laatst online: 17:07
Met hem ^^. Maar als voorbeeld zou je ook naar reflectie kunnen kijken. Je kunt namelijk ook runtime IL schrijven. Dit is best wel lastig om te leren, kun je dit, dan kun je meteen ook heel veel.

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 22-10 10:28
Ik heb wel eens applicaties gezien die dit konden, als voorbeeld een Patientdosier. De klant kon zelf een textveld toevoegen aan zijn gui en deze werd ook gelijk in de database opgeslagen.

Is hier een standaardmethode voor?

EDIT: die NameValueCollection ziet er goed uit! Daar kan ik denk ik wel wat mee ;)

[ Voor 15% gewijzigd door ZeroCode op 25-02-2008 16:34 ]


  • L-VIS
  • Registratie: April 2005
  • Laatst online: 17:07
Je haalt denk ik wat door elkaar. In C# kan ik natuurlijk gewoon velden in mijn GUI aanmaken at runtime. Daarnaast kun je ook nog gewoon code genereren at runtime, dat is iets compleet anders. Maar als je wilt dat je een applicatie veranderd als de database veranderd, dat kan. Ik zou het dan niet te moeilijk maken, en of een XML-tje maken die de velden bijhoud en dan at runtim textvelden / dropdown etc toevoegen aan je GUI.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 05-11 19:33
Voor dit soort dingen zijn indexers ook handig. Daar zou ik ook even naar kijken. Dit kun je dan doorlussen naar zo'n NameValueCollection.

Noushka's Magnificent Dream | Unity


  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 22-10 10:28
L-VIS schreef op maandag 25 februari 2008 @ 16:38:
Je haalt denk ik wat door elkaar. In C# kan ik natuurlijk gewoon velden in mijn GUI aanmaken at runtime. Daarnaast kun je ook nog gewoon code genereren at runtime, dat is iets compleet anders. Maar als je wilt dat je een applicatie veranderd als de database veranderd, dat kan. Ik zou het dan niet te moeilijk maken, en of een XML-tje maken die de velden bijhoud en dan at runtim textvelden / dropdown etc toevoegen aan je GUI.
Probleem hierbij is dat het dan niet meer multi user werkt (Tenzij je de xml file doorgeeft aan alle andere gebruikers ). Zoals het voorbeeld dat ik hierboven aangeef: Patient gegevens. Als je lokaal xml files bij gaat houden lijkt me dat een drama. Dit kan niet de manier zijn.

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

ZeroCode schreef op maandag 25 februari 2008 @ 16:47:
[...]

Probleem hierbij is dat het dan niet meer multi user werkt (Tenzij je de xml file doorgeeft aan alle andere gebruikers ). Zoals het voorbeeld dat ik hierboven aangeef: Patient gegevens. Als je lokaal xml files bij gaat houden lijkt me dat een drama. Dit kan niet de manier zijn.
xml is een database type net als varchar, int en datetime. Een xml datatype is net zo multi-user als elk ander veld in de tabel. Het xml datatype is beschikbaar in Microsoft SQL Server 2005 en 2008. Je kunt zelfs de waarde in de xml direct updaten (update tblXX set XmlField.Update(//field[@name='Length'], 23) where ID=68).

Als een onbekende database driver probeert om het volledige xml veld op te vragen dan is MSSQL zelfs zo 'slim' om het veld dan als Text terug te geven.

Het probleem is niet zo zeer het aanmaken en tonen van de velden, het probleem is hoe je zorgt dat de applicatie ze ook daadwerkelijk gebruikt (validatie, zoeken, etc). Doe je niets met deze velden (behalve ergens alleen maar tonen), dan kun je net zo goed een multi-line textbox neer knallen op het formulier.

Stel een klant maakt het veld Temperatuur voor een patient record aan. Hoe zorgt je er dan voor dat de inhoud bijvoorbeeld een waarde is tussen 0 en 50 graden celsius is? Hoe kun daarmee een week rapport maken van alle patienten met onderkoeling? Stel er dokter wil een loopup veld (dropdown) op geloofs overtuiging, hoe bouw je dan dynamisch de relatie tussen de mogelijke waardes en de selectie? Of wat als het tijdstip van overlijden ingevoerd moet kunnen worden. Deze datum kan nooit voor de geboortedatum liggen. Hoe ga je met dat soort 'uitdagingen' om? Dat lijken mij je echter problemen. Het opslaan van deze gegevens kan op zoveel manieren dat dat geen probleem mag zijn..

If it isn't broken, fix it until it is..


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Welke oplossing het beste is is ook een beetje afhankelijk van wat je precies wilt.

Je kunt perfect een "Database" in je database maken door een tabel Properties en een tabel Values en dergelijke te maken. Echter word je programma er niet duidelijker/sneller op.

Je kunt het best zorgen dat je zo veel mogenlijk properties gewoon netjes in je database definieert en eventueel voor extra toe te voegen properties het database in database princiepe gebruiken.

Maar zoals al gezegd de beste oplossing is ook afhankelijk van wat je precies wilt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Ruudjah
  • Registratie: November 1999
  • Laatst online: 06-09 20:58

Ruudjah

2022

DIT BERICHT IS PREVENTIEF VERWIJDERD DOOR DE GEBRUIKER

[ Voor 97% gewijzigd door Ruudjah op 02-12-2009 00:17 ]

TweakBlog


  • whoami
  • Registratie: December 2000
  • Laatst online: 01:11
L-VIS schreef op maandag 25 februari 2008 @ 16:14:
Met hem ^^. Maar als voorbeeld zou je ook naar reflectie kunnen kijken. Je kunt namelijk ook runtime IL schrijven. Dit is best wel lastig om te leren, kun je dit, dan kun je meteen ook heel veel.
Ik wil de eerste applicatie wel eens zien die dmv/mbhv reflection code genereert :)

https://fgheysels.github.io/


  • Ruudjah
  • Registratie: November 1999
  • Laatst online: 06-09 20:58

Ruudjah

2022

DIT BERICHT IS PREVENTIEF VERWIJDERD DOOR DE GEBRUIKER

[ Voor 96% gewijzigd door Ruudjah op 02-12-2009 00:17 ]

TweakBlog


  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 22-10 10:28
Ruudjah schreef op dinsdag 26 februari 2008 @ 22:57:
Dit artikel op Codeproject is een implementatie van dynamic properties. Afhankelijk van je applicatie kan je een NameValueCollection gebruiken, maar dat is niet altijd performant of wenselijk. Voor de echte performance kan je beter de implementatie van dat artikel gebruiken/aanpassen. Afgezien van de initialisatie van een property (wat via reflectie gebeurd en daarom niet al te snel is) is dit sneller dan een NameValueCollection omdat je eigenlijk een property hebt geimplementeerd in je applicatie.

Overigens is er genoeg te vinden op het web met betrekking tot dynamic properties.
Holy shiz, dit gaat me echt iets te ver. Ik denk dat we maar een andere oplossing moeten gaan zoeken. Ik zoek nog even door...

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:11
Ruudjah schreef op dinsdag 26 februari 2008 @ 23:23:
Hiero een mooi voorbeeld, maar ik kan het je pas laten zien als de app klaar is en gereleased mag worden. Maar het kan dus, en wordt inderdaad gebruikt. Hier voor een XML file waar dynamisch properties worden gespecificeerd, wat via reflectie in de software wordt gereflecteerd (naming anyone :+)

Dus ja, via reflectie wordt hier code gegenereerd :).
Eh ...
AFAIK kan je met reflection enkel je code gaan 'inspecteren' en kan je helemaal niets toevoegen. Laat eens een stukje zien.
't Enige waar ik kan aan denken is dat je IL emitting gebruikt

https://fgheysels.github.io/


  • Flard
  • Registratie: Februari 2001
  • Laatst online: 16-11 21:27
Ehmmm...
Ik denk als je via emitting je eigen properties/members gaat toevoegen aan een class, dat je (in 99% van de gevallen) een slecht objectmodel hebt.
(Daarbij komt nog dat je bij een dergelijke implementatie geen gebruik kunt maken van intellisense, je debugger maar half werkt en je compiler je ook niet kan waarschuwen voor (mogelijke) fouten).

Over het algemeen kom je met een goed ontworpen generic collection al een heel end.. ;) :+

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Ruudjah schreef op dinsdag 26 februari 2008 @ 22:57:
Dit artikel op Codeproject is een implementatie van dynamic properties. Afhankelijk van je applicatie kan je een NameValueCollection gebruiken, maar dat is niet altijd performant of wenselijk.
Er zijn genoeg dictionary collections welke een indexing algorithme gebruiken voor de keys. Bovendien moet je sowieso dynamisch gaan werken in de GUI om velden e.d. toe te voegen, en dan is gewoon een collection stukken handiger dan via reflection de objecten te gaan inspecteren. Ik kan me nauwelijks voorstellen dat een index lookup (veel) trager gaat zijn dan reflection.

https://niels.nu


  • Ruudjah
  • Registratie: November 1999
  • Laatst online: 06-09 20:58

Ruudjah

2022

DIT BERICHT IS PREVENTIEF VERWIJDERD DOOR DE GEBRUIKER

[ Voor 101% gewijzigd door Ruudjah op 02-12-2009 00:17 ]

TweakBlog


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ruudjah schreef op donderdag 28 februari 2008 @ 12:55:
[...]

Inderdaad, en dat is een onderdeel van reflectie hoewel het de term reflectie natuurlijk niet echt dekt.


[...]

Niet mee eens. Je moet reflectie alleen gebruiken als het echt nodig is. Maar in de gevallen dat het handig is, hoeft het niet het gevolg van een slecht objectmodel te zijn. Eensch, een NameValueCollection heeft ook grote voordelen tov het gebruik van ingewikkelde, lastig te bergrijpen classes met reflectie. (ik begrijp het wel, maar degene die over 3 jaar de code gaat maintainen ook nog?)

Als ik er tijd voor heb zal ik eens een mooi voorbeeld uit de code destilleren en er een benchmark aan hangen tov een NameValueCollection.
Maar in veel gevallen zal de lookup van de properties niet de bottleneck zijn in een applicatie. Meestal valt er op andere gebieden een stuk meer winst te behalen.

En je kent het gezegde wel: "Premature optimization is the root of all evil"

Er zullen best wel gevallen zijn dat IL emitting voor custom properties de juiste oplossing zijn, maar in de meeste gevallen zijn er denk betere oplossingen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Ruudjah
  • Registratie: November 1999
  • Laatst online: 06-09 20:58

Ruudjah

2022

DIT BERICHT IS PREVENTIEF VERWIJDERD DOOR DE GEBRUIKER

[ Voor 94% gewijzigd door Ruudjah op 02-12-2009 00:17 ]

TweakBlog


  • Flard
  • Registratie: Februari 2001
  • Laatst online: 16-11 21:27
Ruudjah schreef op donderdag 28 februari 2008 @ 12:55:
[...]

Niet mee eens. Je moet reflectie alleen gebruiken als het echt nodig is. Maar in de gevallen dat het handig is, hoeft het niet het gevolg van een slecht objectmodel te zijn. Eensch, een NameValueCollection heeft ook grote voordelen tov het gebruik van ingewikkelde, lastig te bergrijpen classes met reflectie. (ik begrijp het wel, maar degene die over 3 jaar de code gaat maintainen ook nog?)

Als ik er tijd voor heb zal ik eens een mooi voorbeeld uit de code destilleren en er een benchmark aan hangen tov een NameValueCollection.
Reflection is handig. (Ik maak zelf bijvoorbeeld veel gebruik van Attributes).

Emitting (wat wellicht een onderdeel is daarvan, maakt me niet uit), lijkt me echter zoals ik zei in nagenoeg alle gevallen 'slecht'. Zodra je met emitting properties aan een klasse wilt gaan toevoegen ga ik me namelijk heel erg afvragen of je de abstractie niet een niveau te diep doorvoert.
Ik denk dat je dan juist collections moet gebruiken.

In het voorbeeld van de TS: in dat geval zou ik zelf, als het zo voorkomt een collection CustomProperties toevoegen, wellicht van het type NameValueCollection, Hashtable of Dictionary.
Het feit dat een klant ze toevoegt wil namelijk toch al zeggen dat je interface ook dynamisch opgebouwd moet worden. In dat geval kun je net zo goed door je CustomProperties collection loopen. Dan kun je iedere CustomProperty bijvoorbeeld een Editor property geven, e.d.). Scheelt zich in lastige constructies aan zowel de emitting kan als de reflection kant bij het ophalen. En aangezien de klant ze zelf toevoegt, wil dat waarschijnlijk ook zeggen dat je ze niet in de core-code gebruikt, dus speelt lijkt me de performance ook een mindere rol. (Kan natuurlijk wel, maar dan moet je toch eerst meten: emitting/reflection vs. ICollection ;) )

(Of wat ik zelf onlangs heb geimplementeerd voor een bepaald type DB2 database: een eigen code generator die de .cs files genereerd voor iedere tabel en die vervolgens compiled tot een dll, die door een andere applicatie gebruikt kan worden.)

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ruudjah schreef op donderdag 28 februari 2008 @ 13:33:
De keus om dynamisch properties toe te voegen heeft een andere achtergrond dan performance (en dus optimalisatie).
Kun je dan mischien een reden vertellen waarom jullie voor dynamische properties gekozen hebben? Ik kan er zelf niet zo goed andere redenen voor bedenken ( Behalve als je iets als een proxy voor een andere class runtime wilt maken ).

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Ruudjah
  • Registratie: November 1999
  • Laatst online: 06-09 20:58

Ruudjah

2022

DIT BERICHT IS PREVENTIEF VERWIJDERD DOOR DE GEBRUIKER

[ Voor 97% gewijzigd door Ruudjah op 02-12-2009 00:18 ]

TweakBlog


  • Zyphrax
  • Registratie: September 2001
  • Laatst online: 04-04-2023
Ik weet niet of het mogelijk is voor je applicatie, maar misschien is het gebruik van DataTables hier interessanter dan eigen entiteiten. Je kan een DataTable een stuk dynamischer vullen.

Any sufficiently advanced technology is equivalent to magic.


  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 22-10 10:28
Zyphrax schreef op donderdag 28 februari 2008 @ 17:33:
Ik weet niet of het mogelijk is voor je applicatie, maar misschien is het gebruik van DataTables hier interessanter dan eigen entiteiten. Je kan een DataTable een stuk dynamischer vullen.
Dat is juist het probleem ik wil van die datatables af. Ik wil gaan werken met het Entity Framework. Ik kan alleen geen optie / manier vinden om dynamisch properties/members toe te voegen. Alles lijkt statisch.

Ik heb nu een paar uurtjes met het Entitiy Framework gespeeld maar misschien mis ik iets?

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Business objecten zijn per definitie niet dynamisch. Een business objecten heeft namelijk kennis van de informatie welke het 'vertegenwoordigd'. Als jij ineens dynamisch een veld toevoegt kan het object nooit weten wat het ermee moet doen.

Dynamisch waardes aan de properties van een business object toekennen is wel mogelijk. Via TypeDescriptor.GetProperties (System.ComponentModel) kun je zeer eenvoudig de properties van een object uitlezen.

Heb je al eens naar LINQ 2 SQL gekeken? Kijk vooral eens naar het designer.cs bestand. Neem daarna eens een kijkje in de documentatie van Active Record (Windsor castle) wat een door ontwikkelde versie van NHibernate is.

Overigens is er een zeer goede reden waarom het dynamisch toevoegen van properties niet verstandig is. Het maakt debuggen een heel stuk lastiger. Maar er zijn ook een praktisch issues. Dynamische properties zijn zoals de naam aangeeft dynamisch. Ze zijn er dus niet altijd. Hoe weet jij in je 'view' of een property wel of niet aanwezig is. Als jij namelijk een property probeert te benaderen welke niet is toegevoegd krijg je een keiharde foutmelding op je scherm.

Mijn mening is dat als je een (web)applicatie ontwikkelt je ook weet welke je data je hebt. Maar ik vermoed dat je bezig met met een 'basis' framework welke je wilt customizen als je voor een klant bezig bent. De LINQ 2 SQL classes kun je gewoon overriden en om de nieuwe properties te gebruiken is het voldoende om een 'column' attribute aan elke property te koppelen welke een database veld representeert.

Persoonlijk vind ik Active Record erg fijn werken. NHibernate heeft zijn in de praktijk zich meermalen bewezen en is zeer stabiel. Ik vind het alleen niet fijn om met grote xml configuratie bestanden te werken. Tijdens het compileren worden de Active Record attributen omgezet naar nhibernate configuratie.

If it isn't broken, fix it until it is..

Pagina: 1