获取通过 Func 发送的匿名类型中定义的属性
Getting the properties defined in an anonymous type sent via Func
假设我们有以下 class 定义如下
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; }
}
然后我需要在一个方法中使用这个 class 中的一个或多个属性做一些事情,我想以一种编译安全的方式定义它。所以我想这样调用方法:
MyFunction<Test>(t => new {t.Name, t.Address.AddressText});
然后在 MyFunction 中,我需要知道“名称”和“Address.AddressText”是选定的属性,但我不确定如何获取它
public void MyFunction<T>(Func<T, ?> param){
...
}
所以我的问题是我无法设置 ?以任何好的方式作为 Func
的 TResult
。如果我能正确设置它,我想我可以接受 typeOf(TResult).GetProperties()
,但我觉得我缺少一块来让它工作。
更新
我发现我在这里尝试做的事情有些混乱。我将举一个来自 MongoDB 驱动程序的示例,它的行为方式与我希望我的代码执行的方式相同
所以可以说 testcoll
是 Test
个对象的集合。在那种情况下,这将起作用,并且只会 return 我一个只有名称 属性.
的匿名类型的列表
await testcoll.Find(t => t.Type == "sometype").Project(t => new {t.Name}).ToListAsync();
所以问题基本上是。在Project
中,如何识别Name
是我要从数据库中获取的属性,而结果中的匿名类型是return?
好的,我现在解决了这个问题。可能是我在问题中的解释是问题所在。我想获得参数的编译时安全性,而不是获得编译时的实际值。那当然不行。
所以我希望能够写
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 => new {t.Name, t.Address.AddressText}
,将在方法内转换为包含字符串 "Name"
和 "Address.AddressText"
的列表。
假设我们有以下 class 定义如下
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; }
}
然后我需要在一个方法中使用这个 class 中的一个或多个属性做一些事情,我想以一种编译安全的方式定义它。所以我想这样调用方法:
MyFunction<Test>(t => new {t.Name, t.Address.AddressText});
然后在 MyFunction 中,我需要知道“名称”和“Address.AddressText”是选定的属性,但我不确定如何获取它
public void MyFunction<T>(Func<T, ?> param){
...
}
所以我的问题是我无法设置 ?以任何好的方式作为 Func
的 TResult
。如果我能正确设置它,我想我可以接受 typeOf(TResult).GetProperties()
,但我觉得我缺少一块来让它工作。
更新
我发现我在这里尝试做的事情有些混乱。我将举一个来自 MongoDB 驱动程序的示例,它的行为方式与我希望我的代码执行的方式相同
所以可以说 testcoll
是 Test
个对象的集合。在那种情况下,这将起作用,并且只会 return 我一个只有名称 属性.
await testcoll.Find(t => t.Type == "sometype").Project(t => new {t.Name}).ToListAsync();
所以问题基本上是。在Project
中,如何识别Name
是我要从数据库中获取的属性,而结果中的匿名类型是return?
好的,我现在解决了这个问题。可能是我在问题中的解释是问题所在。我想获得参数的编译时安全性,而不是获得编译时的实际值。那当然不行。
所以我希望能够写
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 => new {t.Name, t.Address.AddressText}
,将在方法内转换为包含字符串 "Name"
和 "Address.AddressText"
的列表。