从匿名类型中获取价值

Sae*_*eid 15 c# asp.net-mvc anonymous-types c#-4.0 asp.net-mvc-3

我有一个方法如下:

public void MyMethod(object obj){

  // implement

}
Run Code Online (Sandbox Code Playgroud)

我称之为:

MyMethod(new { myparam= "waoww"});
Run Code Online (Sandbox Code Playgroud)

那么如何实现MyMethod()获取myparam值呢?

编辑

我用这个:

dynamic d= obj; 
string param = d.myparam; 
Run Code Online (Sandbox Code Playgroud)

但错误上升:

'object' does not contain a definition for 'myparam' 
Run Code Online (Sandbox Code Playgroud)

我也使用断点,我看到d有myparam字符串属性.

有没有办法检查动态类型,如果包含这样的任何属性:

if(d.contain(myparam))?
Run Code Online (Sandbox Code Playgroud)

编辑二

这是我的主要代码:

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
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

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

错误是:

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 
Run Code Online (Sandbox Code Playgroud)

编辑III

这是HtmlHelper定义的AssemblyInfo:

[assembly: AssemblyTitle("MyProject.Presentation")]
[assembly: InternalsVisibleTo("cpanel.MyProject.dev")]
Run Code Online (Sandbox Code Playgroud)

但是还有一个错误:'object' does not contain a definition for 'area' 我使用不同的程序集但是怎么可能呢,当我使用断点时我可以看到我的动态areaobjectareaname属性而且我可以看到它的值,但错误说:'object' does not contain a definition for 'area'我无法想象它怎么可能?

编辑

我更改了程序集,现在动态类型是内部的,但错误仍然像以前一样

Sae*_*eid 27

使用这个:

string area = areaObject.GetType().GetProperty("area").GetValue(areaObject, null);
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 23

好吧,如果您使用C#4,可以使用动态类型:

public void MyMethod(object obj) {
    dynamic d = obj;
    Console.WriteLine(d.myparam);
}
Run Code Online (Sandbox Code Playgroud)

它确实提出了为什么你没有使用命名类型的问题.匿名类型并非真正设计为在这样的不同方法之间共享.

编辑:请注意,如果这是与创建对象的原始代码不同的程序集,则需要使用[InternalsVisibleTo]匿名类型作为内部.


Eri*_*ert 6

首先,正如其他人所说:首先不要这样做.这不是如何使用匿名类型.

其次,如果您愿意这样做,有很多方法可以做到.正如其他人所说,缓慢而危险的方式是使用动态.

快速而危险的方法是使用"通过示例演员:

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 });
}
Run Code Online (Sandbox Code Playgroud)

有没有办法检查动态类型是否包含任何属性?

使用反射.当然,如果您打算使用Reflection,那么首先不需要使用动态.你使用动态来避免使用Reflection,所以如果你打算继续使用Reflection,你也可以继续使用它.

听起来你正在尝试做一些C#中很难做的事情.我会重新评估你是否想要这样做,如果你这样做,C#是否适合你.像IronPython这样的动态语言可能更适合您的任务.

  • @Saeid:按示例进行的转换仅适用于*all在同一个程序集*中的匿名类型.如果在一个程序集中声明一个名为C的类型,则不能将其转换为另一个程序集中也称为C的其他类型; 匿名类型是一样的.匿名类型不打算跨程序集使用;**使用名义类型**,而不是匿名类型. (2认同)