2014-10-24 16 views
6

Sto costruendo una libreria di classe universale dal codice esistente, e ricevo alcuni avvisi del compilatore che io per tutta la vita non riesco a capire cosa fare con.Come posso sostituire Marshal.SizeOf (Object) con Marshal.SizeOf <T>()?

Ho codice in questo modo:

void SomeMethod(Object data) 
{ 
    var size = Marshal.SizeOf(data); 
    ... 
} 

Il codice costruisce, ma nel progetto diuniversale (e, immagino, .NET 4.5.1 e progetti superiori) ottengo il seguente avviso del compilatore:

avvertimento CS0618: 'System.Runtime.InteropServices.Marshal.SizeOf (oggetto)' è obsoleto: 'SizeOf (Object) potrebbe non essere disponibile nelle versioni future. Utilizzare invece SizeOf <T>().

Ma come si crea un sostituto per Marshal.SizeOf(Object) nel caso di cui sopra con il metodo dei parametri-meno generico Marshal.SizeOf<T>()? In teoria, potrei non avere idea di quale sia il tipo data?

È perché l'utilizzo di Marshal.SizeOf(Object) è considerato una cattiva pratica che è stato attribuito Obsolete? E il messaggio da portare a casa dovrebbe davvero essere "refactoring del codice completamente"?

+3

Certamente non è obsoleta in 4.5.1. Immagino che sia stato reso obsoleto in particolare nell'assemblaggio di riferimento universale perché è un problema al collo per il compilatore in anticipo di .NET Native. Non è chiaro il motivo per cui non si può semplicemente rendere SomeMethod generico. Se non è possibile, la toolchain di .NET Native può causare anche problemi. –

+1

Ho rimosso la mia risposta. Vedere [SizeOf (T) su MSDN] (http://msdn.microsoft.com/en-us/library/vstudio/dn261467 (v = vs.110) .aspx). Ci vuole "" e anche un parametro. Puoi passare il tuo oggetto lì, e verrà misurato correttamente. Sono abbastanza sicuro che dovresti riuscire a passare anche 'Marhal.SizeOf (dati)'. Complimenti a NemanjaBoric per averlo indicato. Non sto scrivendo una risposta, visto che non posso verificare (non ho il compilatore 4.5.1 ora) se funziona davvero, ma non vedo perché non dovrebbe, visto che prende l'oggetto finale e può leggerlo vero tipo. – quetzalcoatl

+0

Grazie per tutto il tuo aiuto, @quetzalcoatl e NemanjaBoric. Sciocco da parte mia perdere questo sovraccarico di 'SizeOf'. Farò un tentativo e vedere come si adatta alle mie esigenze. –

risposta

0

Ok, dopo aver ottenuto i tuoi commenti sembra che tutto ciò che serve è già lì:

SizeOf<T>(T): Penso che questo è il metodo che vi serve, ma non c'è bisogno di definire il parametro generico esplicitamente, a causa a type inference. È sufficiente scrivere var size = Marshal.SizeOf(myStructure); e il compilatore estrarrà il tipo dall'oggetto specificato e compila il parametro generico.

SizeOf<T>(): Questo metodo è utile quando la propria classe è forse già una classe generica e si dispone di un T ma non di un'istanza reale del tipo generico utilizzato. In tal caso, questo metodo dovrebbe essere scelto.

Che ne dite di questo approccio riflessione:

private static int MySizeOf(object structure) 
{ 
    var marshalType = typeof(Marshal); 
    var genericSizeOfMethod = marshalType.GetMethod("SizeOf", Type.EmptyTypes); 
    var sizeOfMethod = genericSizeOfMethod.MakeGenericMethod(structure.GetType()); 
    var size = (int)sizeOfMethod.Invoke(null, null); 

    return size; 
} 

+1

Pensiero interessante, anche se non mi sento del tutto a mio agio nell'introdurre un metodo di riflessione per risolvere questo problema. Penso anche che il tuo codice potrebbe richiedere un adattamento: (1) Non penso che 'Type.GetMethod' sia disponibile nei progetti Universal, potresti dover attraversare' TypeInfo.DeclaredMethods' per ottenere gli overload 'SizeOf'; (2) Penso che manchi l'opportunità di passare l'oggetto 'structure' al metodo, forse il secondo argomento nella chiamata' Invoke' dovrebbe essere 'new [] {structure}' invece di null? –

+0

Mai lavorato con gli universali, quindi non conosco le loro restrizioni. Per la chiamata Invoke non è necessario passare la struttura, perché abbiamo già estratto il tipo e utilizzato quello per la chiamata generica 'Marshal.SizeOf ()'. – Oliver

+0

Ma la dimensione non gestita dell'oggetto 'structure' è sempre la stessa? Quindi, perché sono presenti due sovraccarichi '' Marshal.SizeOf ',' Marshal.SizeOf () 'e' Marshal.SizeOf (T) ', in [il 4.5.1 e successivi framework] (http: // msdn. microsoft.com/en-us/library/vstudio/system.runtime.interopservices.marshal.sizeof(v=vs.110).aspx)? E, sono abbastanza sicuro che non puoi fare 'Type.GetMethod' in un progetto Universal, dal momento che il metodo non è disponibile per le moderne app Windows (f.k.a. Metro). –