25

I have a method as following:

public void MyMethod(object obj){

  // implement

}

And I call it like this:

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

So how can I implement MyMethod() to get myparam value?

Edit

I use this:

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

but the error rise :

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

also I use breakpoint and I see the d have myparam string property.

And is there any way to check dynamic type to if contain any property like this:

if(d.contain(myparam))?

Edit II

This is my main code:

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
}

and call it as:

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

And Error is:

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 

Edit III

This is my AssemblyInfo of HtmlHelper definition:

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

but there is an error yet: 'object' does not contain a definition for 'area' I use different assemblies but how can it possible, when I use breakpoint I can see that my dynamic areaobject have area name property and also I can see the value of that, but the error say: 'object' does not contain a definition for 'area' I can't figure it how it can be possible?

Edit

I change the assembly and now dynamic type is internal but the error remains as before

Saeid
  • 13,224
  • 32
  • 107
  • 173
  • 1
    Anonymous types are only valid in the scope where you create them. In this case you will not be able to use it in MyMethod – Jon Mar 17 '12 at 12:51
  • Why are you trying to do this? It's most likely a bad idea. – svick Mar 17 '12 at 13:37
  • I was same answer with this article. https://stackoverflow.com/questions/5286695/how-do-i-get-data-from-an-anonymous-type-thats-been-converted-to-an-object/30462304#30462304 – Kim Ki Won May 26 '15 at 15:07

5 Answers5

41

Use this one:

string area = areaObject.GetType().GetProperty("area").GetValue(areaObject, null);
Saeid
  • 13,224
  • 32
  • 107
  • 173
27

Well, you could use dynamic typing if you're using C# 4:

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

It does beg the question of why you're not using a named type though. Anonymous types aren't really designed to be shared among different methods like this.

EDIT: Note that if this is in a different assembly to the original code creating the object, you'll need to use [InternalsVisibleTo] as anonymous types are internal.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you for answer but there is an error, I use like this: `dynamic d= obj; string param = d.myparam;` but the error rise : 'object' does not contain a definition for 'myparam' also I use breakpoint and I see the `d` have myparam string property. – Saeid Mar 17 '12 at 13:21
  • And is there any way to check dynamic type to if contain any property like this: `if(d.contain(myparam))`? – Saeid Mar 17 '12 at 13:28
  • 1
    @Saeid, this could should work. Could you post the full code that doesn't work for you? To check whether an object has some property, you would need to use reflection or catch the exception the `dynamic` binding throws. – svick Mar 17 '12 at 13:37
  • @Saeid: Is this in a different assembly? Anonymous types are internal. Will edit. – Jon Skeet Mar 18 '12 at 07:34
  • @Jon Skeet I use this form: `[assembly: InternalsVisibleTo("anotherAssemblyName")] public static class LinkExtensions {` and there is a warning: `'assembly' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'type'. All attributes in this block will be ignored. D:\Projects\MyProject\HtmlHelpers\LinkExtensions.cs 13 3 MyProject ` – Saeid Mar 18 '12 at 07:55
  • @Saeid: Put it outside any namespace declaration. AssemblyInfo.cs is the usual place. – Jon Skeet Mar 18 '12 at 07:58
  • @JonSkeet I put it in AssemblyInfo file as you say but the error remain as before – Saeid Mar 18 '12 at 08:08
  • @JonSkeet I change the code location to the same assembly now, I have just one assembly but the error remains as before – Saeid Mar 18 '12 at 08:51
6

First off, as others have said: don't do this in the first place. That's not how anonymous types were intended to be used.

Second, if you are bent upon doing it, there are a number of ways to do so. The slow and dangerous way is to use dynamic, as others have said.

The fast and dangerous way is to use "cast by example:

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?

Use Reflection. Of course, if you are going to use Reflection then there is no need to use dynamic in the first place. You use dynamic to avoid using Reflection, so if you are going to be using Reflection anyways, you might as well just keep on using it.

It sounds like you are trying to do something that is hard to do in C#. I would reevaluate whether you want to be doing that, and if you do, whether C# is the language for you. A dynamic language like IronPython might be a better fit for your task.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • There is an error:`[A]<>f__AnonymousType0`1[System.String]cannotbecastto [B]<>f__AnonymousType0`1[System.String].Type A originates from 'App_Web_c3frks2a,Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' in the context'Default'at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\~..\App_Web_c3frks2a.dll'. Type B originates from 'Myproject,Version=1.0.0.0,Culture=neutral, PublicKeyToken=null'in the context 'Default'at location 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\~..\assembly\dl3\~ ..\MyProject.DLL` – Saeid Mar 18 '12 at 07:42
  • 2
    @Saeid: Casting by example only works on anonymous types that are *all in the same assembly*. If you declare a type called C in one assembly, you cannot convert that to a different type also called C in a different assembly; anonymous types are the same way. Anonymous types were not intended to be used across assemblies; **use a nominal type**, not an anonymous type. – Eric Lippert Mar 18 '12 at 15:36
1

Everybody says "don't do it in the first place", but this is exactly what asp.mvc does! (Don't get me wrong I don't like it myself, but if you are writing custom html helpers you want to call them the way you call the normal html helpers...)

And you can use asp.mvc to make your life easier:

public void MyMethod(object obj){
  var dic=new System.Web.Routing.RouteValueDictionary(obj);
  string param=dic["myparam"] as string;
}
Nadav
  • 357
  • 3
  • 10
  • "but so and so does it too" isn't really a good justification for anything, ever. – Servy Feb 14 '13 at 14:58
  • 4
    When I'm writing an ASP.MVC helper function it should, in my opinion, conform to the standards of ASP.MVC helper functions. And if most ASP.MVC helper functions accept parameters as anonymous types then it I think I should support that. Otherwise it cause – Nadav Mar 05 '13 at 08:09
  • Also, If I'm writing code that accepts parameters as other than anonymous types and then need to pass it to (for example) the additionalViewData parameter for Html.EditorFor() then I have to convert my parameters to an anonymous object. Do you know how to convert a Dictionary to an anonymous object ? – Nadav Mar 05 '13 at 08:21
0

Another way is convert anonymous data to json and then convert to c# json object. You can read all data with this way easily.

Ali Rasouli
  • 1,705
  • 18
  • 25