2015-03-05 8 views
5

Ho un metodo che interroga una pausa API dove eseguo una mappatura da JSON a un oggetto. Poiché la stringa di query e il tipo di oggetto I passano a questo metodo devono sempre corrispondere, volevo includere la stringa di query come stringa statica.Come posso associare una stringa statica a un tipo di oggetto C#

public class Root 
{ 
    public static string Query; 
} 

public class RootObject : Root, IRootObject 
{ 
    public D d { get; set; } 
    public static new string Query = "AccountSet"; 
} 

public interface IRootObject 
{ 
    D d { get; } 
} 

public class RestClass 
{ 
    public void Connect<T>() where T : Root, IRootObject 
    {  
     T.Query <-- fails (not actual code. Just to show my problem) 
    } 
} 
+2

In C# (o nella CLI in generale), la nozione di membri statici virtuali non esiste (sfortunatamente, IMO). Pertanto, quello che stai cercando di fare non può funzionare, dato che 'T.Query' (anche se fosse compilabile) non sarebbe polimorfico. –

+0

È possibile scrivere il proprio attributo con parametro stringa per contrassegnare le classi. F.e. '[QueryName (" AccountSet ")] public class RootObject ...'. Quindi è possibile utilizzare la riflessione per estrarre i dati di stringa. –

risposta

4

Si potrebbe utilizzare un attributo personalizzato per questo:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 
public sealed class QueryAttribute : Attribute 
{ 
    public string QueryString { get; private set; } 

    public QueryAttribute(string queryString) 
    { 
     QueryString = queryString; 
    } 

    public static string GetQueryStringForType(Type type) 
    { 
     var queryAttr = type.GetCustomAttributes(typeof(QueryAttribute), false) 
          .FirstOrDefault() as QueryAttribute; 

     return queryAttr != null ? queryAttr.QueryString : null; 
    } 
} 

utilizzare sul vostro classi:

[Query("AccountSet")] 
public class RootObject : Root, IRootObject 
{ 
    public D d { get; set; } 
} 

e recuperare il valore in questo modo:

public void Connect<T>() where T : Root, IRootObject 
{ 
    var query = QueryAttribute.GetQueryStringForType(typeof(T)); 
} 
+0

Se si astraggono il recupero dell'attributo Query in un metodo di estensione per 'Tipo', il codice potrebbe essere abbastanza pulito. – Baldrick

+0

@Baldrick hai ragione. Ho refactored questo un po '. Avere un tale metodo nella tua cassetta degli attrezzi è una buona idea. –

+0

@Hmm .. non proprio quello che avevo in mente. Compilare? Non sono sicuro che con 'typeof (T)' nel mezzo di una classe non generica ... – Baldrick

1

Al contrario di lingue come Delphi, C# e la CLI .NET in generale non supportano il concetto di polimorfismo statico.

Pertanto, sarà necessario qualche altro modo per collegare le informazioni specifiche di tipo per i tipi di, due dei quali suggerisco qui:

  1. È possibile utilizzare un custom attribute per segnare la vostra classe. Questo attributo può essere recuperato da typeof(T) con metodi di riflessione come GetCustomAttributes. Una volta che hai definito la tua classe di attributi, questi attributi sono abbastanza facili da dichiarare per ogni tipo che vuoi passare a T. Lo svantaggio è che non c'è modo di verificare in fase di compilazione se ogni classe passata a T è adornata da tale attributo.
  2. In alternativa, è possibile utilizzare un "oggetto informazioni". Creare una classe base ObjectInfo<T> che funge da fabbrica per un'istanza di tipo Te come memoria per alcune metainformazioni su T, ad esempio la stringa Query. Per ogni tipo che si desidera passare a T, sottoclasse la classe ObjectInfo<T> where T : Root (ad esempio, crea una classe RootObjectInfo : ObjectInfo<RootObject> che sostituisce la proprietà Query di ObjectInfo<T> per restituire la stringa appropriata). Quindi, modificare Connect<T> quindi richiede un argomento ObjectInfo<T>.
Problemi correlati