【问题标题】:Getting the properties defined in an anonymous type sent via Func获取通过 Func 发送的匿名类型中定义的属性
【发布时间】:2020-12-10 11:54:12
【问题描述】:

假设我们有以下这样定义的类

class Test {
    public string Name { get; set; }
    public string Type { get; set; }
    public string SomeOtherValue { get; set; }
    public Address Address { get; set; }
}

class Address {
    public string AddressText { get; set; }
    public string PostalCode { get; set; }
}

然后我需要在一个方法内部对这个类中的一个或多个属性做一些事情,我想以一种编译安全的方式定义哪个。所以我想这样调用方法:

MyFunction<Test>(t => new {t.Name, t.Address.AddressText});

然后在 MyFunction 中我需要知道“Name”和“Address.AddressText”是选定的属性,但我不知道如何获得它

public void MyFunction<T>(Func<T, ?> param){
    ...
}

所以我的问题是我无法设置 ?以任何好的方式作为FuncTResult。如果我能正确设置它,我想我可以使用typeOf(TResult).GetProperties(),但我觉得我错过了让它工作的一部分。

更新

我发现我在这里尝试做的事情很混乱。我将给出一个来自 MongoDB 驱动程序的示例,其行为方式与我希望我的代码执行的方式相同

所以可以说testcollTest 对象的集合。在这种情况下,这将起作用,并且只会返回一个只有 Name 属性的匿名类型列表。

await testcoll.Find(t => t.Type == "sometype").Project(t => new {t.Name}).ToListAsync();

所以问题基本上是。在Project 内部,如何确定Name 是我要从数据库中获取的属性,并在结果中以匿名类型返回?

【问题讨论】:

  • 抱歉,打错字了。所以习惯于在 IDE 中编写 prop 来自动完成属性 ;)
  • 为什么你不能创建一个类/结构,甚至是一个元组?调用者可以选择不同的属性吗?
  • 是的,它与搜索投影结合使用。这是为了表明我有兴趣返回哪些字段,并且每次调用 MyFunction 时都会有所不同
  • 那么MyFunction 不能确定属性NameAddressText 存在,对吗?您可能对“那些领域不感兴趣”。 MyFunction 无法在编译时类型安全的情况下执行此操作,因为没有可变参数泛型,除非您每次都对恒定数量的字段感兴趣。
  • 对于编译类型安全,我的意思是调用函数。我希望参数是新的 {t.Name, t.Address.AddressText} 而不是像这个新的 []{ "Name", "Address.AddressText"} 这样的魔法字符串数组。但我知道获取发送的实际值必须在运行时完成,这很好。

标签: c# reflection anonymous-types


【解决方案1】:

好的,我现在解决了这个问题。可能是我在问题中的解释是问题所在。我想获得参数的编译时间安全,而不是获得实际值编译时间。那当然行不通。

所以我希望能够写作

MyFunction<Test>(t => new {t.Name, t.Address.AddressText});

而不是

MyFunction<Test>(new {"Name", "Address.AddressText"});

这样我就不会在传入的参数中出现任何拼写错误,并且会确保对 Test 对象的任何更改都会在编译时给我带来错误。

我是这样解决的:

public void MyFunction<T>(Expression<Func<T, object>> lambda)
{
    List<string> arguments;
    if (lambda.Body is NewExpression)
    {
        var args = (lambda.Body as NewExpression).Arguments;
        arguments = args.Select(a =>
        {
                var aText = a.ToString();
                var dotIndex = aText.IndexOf(".");
                var result = aText.Substring(dotIndex + 1);
                return result;
            }).ToList();
        }
        else
        {
            throw new ArgumentException();
        }
    }
    <do whatever I need to do here with the arguments list>
}

因此,对于上面的示例,其中参数为 t =&gt; new {t.Name, t.Address.AddressText},它将被转换为方法中包含字符串 "Name""Address.AddressText" 的列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    相关资源
    最近更新 更多