【问题标题】:Access C# anonymous type object returned from a method [closed]访问从方法返回的 C# 匿名类型对象 [关闭]
【发布时间】:2014-07-31 21:09:02
【问题描述】:

有人写了一个返回对象类型的方法。

public object GetProvider(double personId)
{
    // Some other code here

    return new {
       FirstName = Convert.ToString(reader["FirstName"]),
       LastName = Convert.ToString(reader["LastName"])
    };
}

在不同的代码部分,我们使用这个库方法。

var d = GetProvider(123); 
string fName = d.GetType().GetProperty("FirstName").GetValue(d, null).ToString();

如何改进或简化此代码?我猜他们应该创建一个类并返回它的一个对象而不是对象类型。此外,我还看到在 C#4 中使用 dynamic 的代码。我试过了,但它不适用于对象类型。有什么想法吗?

【问题讨论】:

  • dynamic 怎么不起作用?
  • @Jashaszun: d 被输入为System.Object,它没有FirstName 属性。
  • “改进或简化此代码”——听起来像是 Code Review 的完美候选者
  • 这里正确的解决方案是不从方法返回匿名类型。使用命名类型。
  • 这不是一个坏问题。如您所见,作者必须使用其他人编写的方法。这可能存在于另一个程序集中,并且不允许他更改它。我不明白为什么动态不起作用。你能解释一下吗?

标签: c# c#-4.0 anonymous-types


【解决方案1】:

像这样实现动态:

dynamic d = GetProvider(123);

string fName = d.FirstName;


似乎这部分实际上与原始帖子无关,因为 OP 无法控制方法的返回类型。我将它留在这里是因为它仍然是最佳实践,并且在绝大多数情况下都应该遵循,并且在理想的世界中,原始方法的作者会阅读并改变他或她的方式。

但总的来说,我很想只做一个类型。不需要花费太多的精力来创建一个类来做你想做的事。

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后您可以将所有内容都进行强类型化,而无需使用dynamic。我认为我从未找到真正适合 dynamic 的用途。这很好,因为它写起来又快又容易,但从长远来看,它往往只会在 99% 的实际使用中引起问题。我并不是说它应该被废除,因为 1% 是有用的(我在这里考虑动态数据的序列化,但即使在那里我通常只使用字符串索引器属性),但一般来说,在使用它之前请三思而后行肯定没有更好的解决方案。匿名类型在 LINQ 查询中很有用,所有这些查询都在范围内并已编译,但我不会使用它们更改范围,除非您绝对必须这样做,而且您永远不会这样做。

【讨论】:

  • 应该可以,但我认为这不是一个好方法。
  • @L.B 很公平。我已经更新了我的答案,建议使用预定义的类。
  • 除非你不能这样做,否则应该使用类方法。 C# 是强类型的,您可以利用编译器而不是因为属性名称中的错误字母而出现运行时错误。
  • 感谢您的回复。该库不是我们维护的,因此无法更改那里的代码。在我最初的问题中,我也提到了创建一个预定义的类。感谢您确认该方法。关于动态,不知何故,我总是得到'object' does not contain a definition for 'FirstName'。我可能需要进一步调试,但这是我在运行时看到的。
  • @kuul13 嗯。不幸的是,我不确定你能做什么。我玩过this DotNetFiddle,但它总是抛出异常。您可能只想写一些东西来为您进行反射并将其解析为具体类型。
【解决方案2】:

如果是我,我可能会将 GetProvider 的结果包装在一个强类型类中。下面的类将来自 GetProvider 的响应作为其构造函数的参数。

public class Provider
{
    public Provider(object provider)
    {
        dynamic dynamicProvider = provider;
        this.FirstName = dynamicProvider.FirstName;
        this.LastName = dynamicProvider.LastName;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后替换

var d = GetProvider(123);

var d = new Provider(GetProvider(123));

【讨论】:

  • 如果无法更改GetProvider 的原始代码,这似乎是最不差的解决方案。这样,如果 GetProvider 的返回类型在以后发生变化,您只需找到一个包装类来修复它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 2012-06-04
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多