Domanda

Il titolo dice praticamente tutto. Quando sto riflettendo sulle mie lezioni, il metodo MemberInfo.GetCustomAttributes () manterrà l'ordine degli attributi su un membro o no? La documentazione ufficiale non dice nulla in un modo o nell'altro.


Nel caso ti stia chiedendo perché avrei bisogno di questo, ecco la spiegazione completa. È lungo e non necessario per la domanda come si pone ora, ma forse qualcuno può trovare una soluzione alternativa al problema più grande che non implica affidarsi all'ordine di enumerazione degli attributi.

Sto cercando di creare un framework flessibile per un'applicazione (ASP.NET) che dovrebbe avere una durata piuttosto lunga. Durante il corso otterrà molte forme che dovranno essere accessibili dal menu. Per semplificare la vita degli sviluppatori, ho creato un MenuItemAttribute che puoi applicare alla classe di un modulo. Questo attributo ha una quantità illimitata di parametri stringa nel suo costruttore che consente a uno sviluppatore di specificare esattamente dove risiederà il modulo nel menu. Un tipico esempio di utilizzo potrebbe essere qualcosa come [MenuItem("Company", "Clients", "Orders")] che significherebbe quindi che il menu dovrebbe avere una voce & Quot; Azienda & Quot; in base al quale ci sarebbe un oggetto " Clienti " in base al quale ci sarebbe un articolo " Ordini " - che avrebbe quindi aperto il modulo. Un singolo modulo può avere diversi di questi attributi se necessario - sarà quindi accessibile da diversi punti del menu.

Ovviamente l'intero menu è costruito in fase di esecuzione elencando tutte le classi nei miei assembly e cercando questo attributo. Tuttavia, recentemente ho ricevuto una richiesta per ordinare le voci di menu in modo predefinito. I moduli con funzionalità correlate dovrebbero essere uno accanto all'altro nel menu. Si noti che questo NON è un ordinamento alfabetico, ma un ordine predefinito specificato dagli sviluppatori.

Questo porta quindi al problema: come posso specificare l'ordine in questi attributi? Poiché una MenuItemOrderHintAttribute descrive un'intera gerarchia, la specifica dell'ordine dovrebbe includere anche i numeri dell'ordine per l'intera (o almeno una parte) della gerarchia. Un numero d'ordine solo per il livello inferiore della gerarchia non è sufficiente.

Potrei fare un altro attributo - <=>, ma ciò porterebbe quindi problemi con i casi quando ce n'è più di uno <=>. Da qui la domanda originale.

Potrei anche estendere <=> per prendere due array o un array di coppie, ma ciò complicherebbe molto la sintassi. L'ultima idea è che potrei rendere le stringhe con un formato speciale, ma sarebbe IMHO piuttosto disordinato.


OK, ho un'altra idea. Usiamo l'ordinamento suggerito da Jon Skeet. Ciò consentirà di specificare l'ordine per l'ultimo livello della gerarchia, non quelli superiori. Ma potrei modificare l'attributo in modo che si applichi non solo alle classi, ma anche all'assembly stesso. In questo caso la voce di menu non avrebbe un modulo associato. A livello di assieme questi attributi potrebbero quindi essere utilizzati per specificare l'ordinamento tra i livelli più alti della gerarchia.

Questo è quindi un compromesso tra un sistema di menu centralizzato e decentralizzato. Qualche idea sul perché questa sarebbe una cattiva idea?

È stato utile?

Soluzione

Metterei un singolo valore extra (opzionale) nel costruttore MenuItemAttribute, che è " order " oppure " priorità " ;:

[MenuItem(0, "Company", "Clients", "Orders")]
[MenuItem(1, "Foo", "Bar", "Baz")]

Non sto dicendo che sarebbe carino, ma ti permetterebbe di specificare l'ordine.

Altri suggerimenti

L'ordinamento lessicale degli elementi in un file non è assolutamente non garantito in alcun modo negli insiemi CIL risultanti né nel rispetto dei risultati restituiti da Reflection. Non è nemmeno garantito che questo ordine sia lo stesso per le chiamate ripetute all'interno dello stesso dominio dell'app!

Nota che in passato MS ha infranto questo ordinamento in altre parti della riflessione (notando come lo ha fatto che ciò ha effettivamente causato alcuni problemi per alcuni dei suoi codici), quindi anche se al momento non funziona nulla fermare questa rottura in futuro o su piattaforme diverse.

Prendi in considerazione la possibilità di modificare il tuo modello di attributo per consentire di esprimere direttamente le informazioni semantiche anziché fare affidamento sull'ordinamento.

Purtroppo no, non puoi garantire che l'ordine sarà lo stesso dell'ordine in cui li hai specificati.

Modifica: una soluzione alternativa

Dichiarazione di non responsabilità: mi scuso in anticipo se sto fraintendendo il tuo ultimo problema.

Sembra che tu debba essere in grado di passare n numero di stringhe a MenuItemAttribute e avere LinkedList<String> mantenere l'ordine di queste stringhe come immesso dallo sviluppatore nel costruttore degli attributi.

Ecco una possibile soluzione:

Avere params String[] utilizzare un <=> per mantenere il suo stato. Quindi puoi iterare <=> nel tuo costruttore e aggiungerli a <=> che manterrebbero l'ordine.

Mi sembra che il tuo problema derivi davvero dal fatto che i moduli specificano dove appaiono nel tuo menu, il che significa che stai cercando di creare un menu combinando tutti i moduli in un assieme. Potrebbe essere più semplice se si specifica la struttura del menu separatamente da qualsiasi modulo e si risolvono i moduli da varie proprietà / attributi definiti sulla classe corrispondente a una voce di menu.

per es.

public class MenuItem
{
    string Text { get; }
    Type FormType { get; }
    ICollection<MenuItem> SubItems { get; }
}

Quindi, quando viene selezionata una voce di menu, risolvi il modulo in qualche modo e visualizzalo. Questo approccio ha lo svantaggio che qualsiasi nuovo modulo necessita di una modifica al codice che specifica la struttura del menu insieme al modulo stesso, ma sarà piuttosto minore ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top