6

https://dotnetfiddle.net/446j0U链接重现(在.net 4.7.2 上失败,不在.net core 上)


public class TEST { 

   static public void Main(string[] args)
    {
        var test = new { Text = "test", Slab = "slab"};
        Console.WriteLine(test.Text); //outputs test
        Console.WriteLine(TEST.TestMethod(test));  //outputs slab
    }

    static public string TestMethod(dynamic obj)
    {
        return obj.Slab;
    }
} 

在同一个函数中访问匿名对象工作正常,但是当我尝试在函数中传递它时出现异常

运行时异常(第 14 行):尝试通过方法 'DynamicClass.CallSite.Target(System.Runtime.CompilerServices.Closure, System.Runtime.CompilerServices.CallSite, System.Object)' 访问类型 '<>f__AnonymousType0`2'失败的。

堆栈跟踪:

[System.TypeAccessException:尝试通过方法'DynamicClass.CallSite.Target(System.Runtime.CompilerServices.Closure,System.Runtime.CompilerServices.CallSite,System.Object)'访问类型'<>f__AnonymousType0`2'失败。]在CallSite.Target(Closure , CallSite , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,Tret](CallSite site, T0 arg0) at TEST.TestMethod(Object obj) :line 14 at TEST.Main(String[] args ) : 第 9 行


@RandRandom 编辑:

由于赏金期快结束了,我决定编辑这个问题。

到目前为止,给出的答案都未能真正回答手头的问题,只是给出了避免错误的方法。

OP 明确表示(在评论中)他知道变通方法并且目前正在使用变通方法。

这些问题仍然存在

  1. 为什么在 OPs setup 和 dotnetfiddle.net 上出现上述错误?
  2. 如果错误通过更新得到修复,那么 OP 需要更新什么?
  3. 在新的编译器/.Net 版本/Visual Studio 版本中解决了问题吗?

在这里回顾一下到目前为止 OP 的信息:

  • VS 2017
  • .Net 框架 4.8
4

5 回答 5

7

正如C# 文档所说:

匿名类型提供了一种方便的方法,可以将一组只读属性封装到单个对象中,而无需先显式定义类型。类型名称由编译器生成,在源代码级别不可用。每个属性的类型由编译器推断。

有两种明显的方法:

1)用预定义的替换匿名类型:

    public class Container {
        public string Test { get; set; }
        public string Slab { get; set; }
    }

    public static void Main(string[] args) {
        var test = new Container { Text = "test", Slab = "slab"};
        Console.WriteLine(test.Text); //outputs test
        Console.WriteLine(TestMethod(test));  //outputs slab
    }

    public static string TestMethod(dynamic obj) {
        return obj.Slab;
    }

这种方式限制您不使用匿名类型。但它会正常工作。

2) 或者如果您喜欢匿名类型,请使用 ExpandoObject 强制转换。

文档:https ://docs.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?redirectedfrom=MSDN&view=netframework-4.8

示例:https ://sebnilsson.com/blog/convert-c-anonymous-or-any-types-into-dynamic-expandoobject/

于 2019-11-20T08:14:04.493 回答
2

这应该工作,

static public string TestMethod(dynamic obj) {
     return obj.GetType().GetProperty("Slab").GetValue(obj).ToString();
}
于 2019-11-27T11:51:15.373 回答
0

这是一个问题.NET Fiddle。该代码与最新Visual Studio 2017更新 ( 15.9.17) 和.NET 4.7.2.

于 2019-11-29T14:17:30.333 回答
0

您可以将 ExpandoObject 用于动态类型的变量或动态参数。 https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?redirectedfrom=MSDN&view=netframework-4.8

public class TEST { 

   static public void Main(string[] args)
    {
        dynamic test = new ExpandoObject();
        test.Text = "test";
        test.Slab = "slab";
        Console.WriteLine(test.Text);
        Console.WriteLine(TEST.TestMethod(test));
    }

    static public string TestMethod(dynamic obj)
    {
        return obj.Slab;
    }
} 
于 2019-11-25T13:37:06.340 回答
-1

这是 .Net 框架的问题。您必须使用已经存在的数据类型并使用 var。对此进行编码的另一种方法是使用字典。

演示

using System; 
using System.Collections.Generic;

public class TEST 
{ 
   static public void Main(string[] args)
    {
        var test =  new Dictionary<int, string>();
        test.Add(1,"One");
        Console.WriteLine(test); //outputs test
        Console.WriteLine(TEST.TestMethod(test));  //outputs slab
    }

    static public string TestMethod(dynamic obj)
    {
        foreach (KeyValuePair<int, string> item in obj)
        {
            Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
            return item.Value;
        }
        return "";   
    }
} 
于 2019-11-22T18:39:16.643 回答