[C#] Attributes op een interface met reflection

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hoi Tweakers,

Ik probeer doormiddel van reflection de attributen van mijn class op te halen.

Ik heb op een interface een Attribuut gezet op deze manier:
C#:
1
2
[PluginCategory(PluginCategory.Category.All)]
public interface IPlugin {}


Een andere class implementeerd deze interface.

Wanneer ik deze dll dynamisch inlaad controleer ik of die de interface IPlugin implementeerd,
zo ja, dan instantieer ik hem en voeg ik hem toe aan een lijst.

Wanneer ik door deze lijst heen loop om de attributen op te halen loop ik met de debugger door deze functie heen:
C#:
1
2
3
4
foreach (IPlugin plugin in _Main.Plugins.Values)
{
    object[] categorys = plugin.GetType().GetCustomAttributes(typeof(PluginCategory), true);
}


de object[] categorys bevat altijd 0 items, behalve als ik het attribuut ook nog op de class zet die de plugin implementeerd. Dit is niet de bedoeling omdat ik dus ook het attribuut op de interface erbij wil hebben, weet iemand wat ik fout doe?

De gebruikte programmeertaal is C#.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is me een beetje onduidelijk waarom je dat wilt. Elke class die je daar hebt implementeert sowieso IPlugin, dus het is per definitie zo dat het PluginCategory attribuut erop gedefinieerd is.

Overigens is het niet heel lastig om simpelweg alle geïmplementeerde interfaces op te vragen en daar vervolgens weer de attributen van te vragen. De 'true' voor GetCustomAttributes() betekent volgens mij alleen dat hij alleen de base classes afloopt, niet de geïmplementeerde interfaces.

[ Voor 48% gewijzigd door .oisyn op 21-07-2010 18:22 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Alex)
  • Registratie: Juni 2003
  • Laatst online: 21-08 11:20
Als ik http://stackoverflow.com/...ibutes-from-its-interface goed begrijp is dat ook niet mogelijk. Wat ik me dan afvraag is waarom het bij WCF wel werkt, want als ik daar [ServiceContract] en [OperationContract] in mijn interface definieer (en dus niet in de class) werkt het wél.

We are shaping the future


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
.oisyn schreef op woensdag 21 juli 2010 @ 18:13:
Het is me een beetje onduidelijk waarom je dat wilt. Elke class die je daar hebt implementeert sowieso IPlugin, dus het is per definitie zo dat het PluginCategory attribuut erop gedefinieerd is.
Omdat een Plugin bij meerdere Category'en kan horen.
Bij de IPlugin, heb ik dus All gedefinieerd, dit is opzich niet nodig, want ik kan ook controleren of ik alles op wil halen, maar als ik zo nog andere interfaces definieer met daarin een andere Category, wil ik op deze manier een soort van filteren.

@Alex)
Jou linkje is ook interessant, zal deze vanavond nog even goed doornemen.

[ Voor 6% gewijzigd door Verwijderd op 21-07-2010 18:40 ]


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Ik vind het niet logisch om dat attribuut op de interface te declareren en niet op de class die de interface implementeerd. Zoals je het nu hebt zul je dus meerdere plugin interfaces hebben, elk behorende bij een bepaalde categorie. Dat is om twee redenen niet logisch:

1. Waarom heb je dan uberhaupt het attribuut nodig? Als elke plugin interface bij een categorie hoort dan weet je toch al door het type van het interface welke categorie het moet zijn? Als je bijvoorbeeld categoriën All, A, B en C hebt dan kun je dus interfaces IPluginAll, IPluginA, IPluginB en IPluginC maken waarbij elke interface het juiste attribuut heeft (attribuut All, A, B, C), of je kunt het hele attribuut gewoon vergeten en gewoon op het type van het interface af gaan. Als een klasse IPluginB implementeerd dan weet je toch al dat het categorie B is? Dan hoef je toch niet nog een keer te kijken welke categorie in het attribuut gedefinieerd is?

Ik neem aan dat je dit hebt gedaan zodat de gebruiker (degene die IPlugin implementeerd) niet meer zelf de categorie hoeft te specificeren, maar dat snap ik nog steeds niet want:

2. Normaal heb je maar één IPlugin interface wat elke plugin moet implementeren. Als je meerdere interfaces hebt dan zal de gebruiker (degene de er een implementeerd) dus moeten kiezen welke hij moet implementeren. Maakt het nou zoveel uit of de gebruiker kiest om een bepaalde plugin interface te implementeren, of één enkele plugin te implementeren en dan een categorie te kiezen? Dat komt toch op hetzelfde neer?


Waar m'n verhaal eigenlijk op neerkomt is: als elke plugin een andere categorie kan hebben dan moet dus de klasse die de plugin interface implementeerd die categorie specificeren, en niet de plugin interface zelf (want dan kun je nooit meer verschillende categoriën hebben, tenzij ze allemaal een andere interface implementeren...)

[ Voor 14% gewijzigd door NickThissen op 21-07-2010 19:20 ]

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik zelf had het idee dat ze allemaal IPlugin moeten implementeren en dan kunnen ze nog optioneel een attribuut op de class zetten waardoor je hem ook nog in een category kan plaatsen.

Er kan ook nog een interface Downloader komen, die ook IPlugin implementeerd.
De downloader zet hem dus in de category Downloader en in All (door IPlugin) maar misschien is dit wel helemaal niet zo slim.

edit: het is dus wel zo, dat je altijd IPlugin moet implementeren ook als je voor de andere Plugin interfaces kies.

edit2: Daarnaast leek het mij logisch om het attribuut ook op de interface te zetten omdat als je IDownloader implementeerd (en daardoor ook IPlugin), je dus bij All en bij Downloader hoort, op je class zou je dan eventueel nog een extra category kunnen zetten, op die manier kun je dus bij meerdere category'en horen.

edit3: (ja ik blijf deze editen :)
De Category class is zo gedefinieerd:
C#:
1
2
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,AllowMultiple=true, Inherited=true)]
public class PluginCategory : Attribute


Het is dus geen enkel probleem om op deze manier bij meerdere category'en te horen doordat je dit attribuut meerdere keren mag definieren.

[ Voor 54% gewijzigd door Verwijderd op 21-07-2010 20:17 ]


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Verwijderd schreef op woensdag 21 juli 2010 @ 20:08:
Ik zelf had het idee dat ze allemaal IPlugin moeten implementeren en dan kunnen ze nog optioneel een attribuut op de class zetten waardoor je hem ook nog in een category kan plaatsen.
Juist. Op de class, en niet op de interface. Elke plugin class moet IPlugin implementeren, elke plugin class kan een andere categorie hebben, dus niet elke plugin class is de All categorie, dus kun je nooit die categorie op de IPlugin interface declareren!

Het werkt toch prima als het attribuut op de class hoort?
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[PluginCategory(PluginCategory.Categories.Downloading)]
public class DownloadPlugin : IPlugin
{
   //...
}

[PluginCategory(PluginCategory.Categories.Colors)]
public class ColorsPlugin : IPlugin
{
   //...
}

[PluginCategory(PluginCategory.Categories.Downloading | PluginCategory.Categories.Colors)]
public class CombinationPlugin : IPlugin
{
   //...
}

// Of voor die laatste kun je mss zelfs DownloadPlugin overerven:
[PluginCategory(PluginCategory.Categories.Downloading | PluginCategory.Categories.Colors)]
public class CombinationPlugin : DownloadPlugin
{
   //...
}

[ Voor 37% gewijzigd door NickThissen op 21-07-2010 20:28 ]

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ja dit kan ook. Alleen leek mij het irritant om IDownloader te implementeren en dan ook nog zelf het attribuut erop te zetten. Zoals hierboven al genoemd werd, kan ik het dan ook aan het interface type zien, dat is inderdaad waar.

Overigens is mijn Category All meer als bedoeling om makkelijk plugins te categoriseren in een venster (op category) en het betekent dus niet dat hij in alle Categorieen getoond moet worden.

edit:
De reden dat ik dus ook voor meerdere interfaces kies, (die dus ook IPlugin implementeren) is omdat ik bepaalde functies wil aanroepen van die plugins. Dit wil ik niet door de plugins de functies te laten registreren bij een Pluginmanager en deze dan met reflection te invoken omdat ik dat niet handig vind.

[ Voor 27% gewijzigd door Verwijderd op 21-07-2010 20:38 ]


Acties:
  • 0 Henk 'm!

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 09-09 10:50
Als je al een interface IDownloader hebt dan is het niet logisch om ook nog een categorie Downloader te hebben. Dan is het logischer dat je voor IDownloader weer aparte categorien hebt (MuziekDownloader, FilmDownloader, GameDownloader, ik noem maar wat) die weer niet gelden voor de algemene IPlugin interface.

Het lijkt me dus dat je hele structuur een beetje in de war is. Om maar even een stom voorbeeld te gebruiken, stel dat het over voertuigen gaat. Je hebt een interface IVoertuig, en classes Auto, Trein, Boot, Fiets, etc, die dat interface implementeren. Categorien zouden zoiets als 'Persoonlijk' (Auto, Fiets) of 'Openbaar' (Trein, Boot), of beide (Boot) kunnen zijn. Je moet dan niet nog een keer een IAuto plugin gaan invoeren die dan ook nog eens de categorie Openbaar kan hebben, dat is gewoon niet logisch.

Mijn iRacing profiel


Acties:
  • 0 Henk 'm!

  • mvhooft
  • Registratie: Juli 2010
  • Laatst online: 19:33
Wat je volgens mij wilt doen is heel makkelijk te doen met MEF (Managed Extensibility Framework).
Dit is onderdeel van .NET 4.0.
Info is op http://mef.codeplex.com/ te vinden.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
NickThissen, ik denk dat je gelijk heb, ik ga nog even goed naar het design kijken.

mvhooft, jou linkje zal ik morgen even bekijken.

Bedankt voor de reacties allemaal :)
Pagina: 1