2012-03-17 16 views
11

Ho un metodo come segue:Ottenere valore dal tipo anonimo

public void MyMethod(object obj){ 

    // implement 

} 

E mi chiamare in questo modo:

MyMethod(new { myparam= "waoww"}); 

Così come posso implementare MyMethod() per ottenere il valore myparam?

Modifica

Io uso questo:

dynamic d= obj; 
string param = d.myparam; 

ma l'aumento di errore:

'object' does not contain a definition for 'myparam' 

anche io uso punto di interruzione e vedo la d ha myparam proprietà della stringa.

E non v'è alcun modo per verificare il tipo dinamico se contenere qualsiasi proprietà come questa:

if(d.contain(myparam))? 

Modifica II

Questo è il mio codice principale:

public static MvcHtmlString SecureActionLink(this HtmlHelper htmlHelper, 
     string linkText, string actionName, string controllerName, 
     object routeValues, object htmlAttributes) { 


    string areaName = 
     (string)htmlHelper.ViewContext.RouteData.DataTokens["area"]; 

     dynamic areaObject = routeValues; 

     if(areaObject != null && !string.IsNullOrEmpty(areaObject.area)) 
      areaName = areaObject.area; 

// more 
} 

e chiamalo come:

<p>@Html.SecureActionLink("Secure Link between Areas", "Index", "Context", 
          new { area = "Settings" }, null)</p> 

e di errore è:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a 
definition for 'area' 

Line 303: dynamic areaObject = routeValues; 
Line 304: 
Line 305: if(areaObject != null && !string.IsNullOrEmpty(areaObject.area)) 
Line 306:  areaName = areaObject.area; 
Line 307: 

Source File: D:\Projects\MyProject\HtmlHelpers\LinkExtensions.cs Line: 305 

Modifica III

Questa è la mia AssemblyInfo di definizione HtmlHelper:

[assembly: AssemblyTitle("MyProject.Presentation")] 
[assembly: InternalsVisibleTo("cpanel.MyProject.dev")] 

ma c'è un errore ancora: 'object' does not contain a definition for 'area' io uso assemblee diverse ma come è possibile, quando uso il punto di interruzione, posso vedere che il mio dinamico areaobject ha area nome proprietà e anche io posso vedere il valore di questo, ma l'errore dire: 'object' does not contain a definition for 'area' Non riesco a capire come può essere possibile?

Modifica

posso cambiare l'assemblaggio e il tipo ora dinamica è interno ma l'errore rimane come prima

+1

I tipi anonimi sono validi solo nell'ambito in cui vengono creati. In questo caso non sarà possibile utilizzarlo in MyMethod – Jon

+0

Perché stai provando a farlo? È molto probabilmente una cattiva idea. – svick

+0

Ho avuto la stessa risposta con questo articolo. https://stackoverflow.com/questions/5286695/how-do-i-get-data-from-an-anonymous-type-thats-been-converted-to-an-object/30462304#30462304 –

risposta

19

Utilizzare questo:

string area = areaObject.GetType().GetProperty("area").GetValue(areaObject, null); 
16

Beh, si potrebbe utilizzare la tipizzazione dinamica se si sta utilizzando C# 4:

public void MyMethod(object obj) { 
    dynamic d = obj; 
    Console.WriteLine(d.myparam); 
} 

Fa sorgere la domanda sul perché non si sta usando un tipo con nome. I tipi anonimi non sono progettati per essere condivisi tra diversi metodi come questo.

MODIFICA: si noti che se questo è in un diverso assieme al codice originale che crea l'oggetto, sarà necessario utilizzare [InternalsVisibleTo] poiché i tipi anonimi sono interni.

+0

Grazie per la risposta, ma c'è un errore, che uso in questo modo: 'dynamic d = obj; string param = d.myparam; 'ma l'errore sale: 'oggetto' non contiene una definizione per 'myparam' anch'io utilizzo breakpoint e vedo la' d' avere proprietà myparam stringa. – Saeid

+0

E c'è un modo per controllare il tipo dinamico se contiene una proprietà come questa: 'if (d.contain (myparam))'? – Saeid

+1

@Saeid, questo potrebbe funzionare. Potresti pubblicare il codice completo che non funziona per te? Per verificare se un oggetto ha qualche proprietà, è necessario usare il reflection o catturare l'eccezione che i lanci vincolanti 'dinamici '. – svick

6

Prima di tutto, come altri hanno detto: non farlo in primo luogo. Non è così che i tipi anonimi sono stati pensati per essere usati.

In secondo luogo, se si è intenzionati a farlo, ci sono diversi modi per farlo. Il modo lento e pericoloso è usare la dinamica, come altri hanno detto.

Il modo più veloce e pericoloso è quello di utilizzare "lanciato da esempio.

static T CastByExample<T>(object obj, T example) 
{ 
    return (T)obj; 
} 
static void M(object obj) 
{ 
    var anon = CastByExample(obj, new { X = 0 }); 
    Console.WriteLine(anon.X); // 123 
} 
static void N() 
{ 
    M(new { X = 123 }); 
} 

is there any way to check dynamic type to if contain any property?

Usa Riflessione Naturalmente, se avete intenzione di utilizzare la riflessione allora non v'è alcuna necessità di utilizzare dinamica primo luogo. si utilizza dinamiche di evitano il ricorso riflessione, quindi se avete intenzione di utilizzare Reflection in ogni modo, si potrebbe anche solo continuare a utilizzarlo.

sembra che un stai cercando di fare qualcosa che è difficile da fare in C#. Vorrei rivalutare se vuoi farlo, e se lo fai, se C# è la lingua per te. Un linguaggio dinamico come IronPython potrebbe essere più adatto al tuo compito.

+0

C'è un errore: ' [A] <> f__AnonymousType0'1 [System.String] cannotbecastto [B] <> f__AnonymousType0'1 [System.String] .Type A deriva da 'App_Web_c3frks2a, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null' in il contesto'Default'at posizione 'C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ File ASP.NET temporanei \ root \ ~ .. \ App_Web_c3frks2a.dll'. Il tipo B ha origine da "Myproject, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null" nel contesto "Default'at location" C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ File temporanei ASP.NET \ root \ ~ .. \ assembly \ dl3 \ ~ .. \ MyProject.DLL' – Saeid

+2

@Saeid: il casting con l'esempio funziona solo su tipi anonimi che sono * tutti nello stesso assembly *. Se dichiari un tipo chiamato C in un assembly, non puoi convertirlo in un altro tipo chiamato anche C in un altro assembly; i tipi anonimi sono allo stesso modo. I tipi anonimi non erano destinati ad essere utilizzati tra gli assembly; ** usa un tipo nominale **, non un tipo anonimo. –

1

tutti dicono "non farlo in primo luogo", ma questo è esattamente quello che fa asp.mvc! (Non fraintendermi non mi piace da solo, ma se stai scrivendo helper html personalizzati vuoi chiamarli come chiami i normali helper html ...)

E puoi usare asp .mvc per semplificarti la vita:

public void MyMethod(object obj){ 
    var dic=new System.Web.Routing.RouteValueDictionary(obj); 
    string param=dic["myparam"] as string; 
} 
+0

"ma così e così lo fa anche" non è davvero una buona giustificazione per nulla, mai. – Servy

+4

Quando sto scrivendo una funzione helper ASP.MVC dovrebbe, a mio parere, essere conforme agli standard delle funzioni di supporto ASP.MVC. E se la maggior parte delle funzioni helper ASP.MVC accetta parametri come tipi anonimi, allora penso che dovrei supportarlo. Altrimenti causa – Nadav

+0

Inoltre, se scrivo codice che accetta parametri diversi da quelli anonimi e quindi devo passarlo (ad esempio) al parametro additionalViewData per Html.EditorFor(), allora devo convertire i miei parametri in anonimo oggetto. Sai come convertire un dizionario in un oggetto anonimo? – Nadav

Problemi correlati