Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用表达式创建强类型变量名列表_C#_Lambda_Reflection_Expression_Expression Trees - Fatal编程技术网

C# 使用表达式创建强类型变量名列表

C# 使用表达式创建强类型变量名列表,c#,lambda,reflection,expression,expression-trees,C#,Lambda,Reflection,Expression,Expression Trees,我有一门课: public class Student { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("age")] public int Age { get; set; } [JsonProperty("country")] public string Country { get; se

我有一门课:

public class Student
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("age")]
    public int Age { get; set; }

    [JsonProperty("country")]
    public string Country { get; set; }
}
我有一个方法:

public static List<string> PrintPropertyNames<T>(params Expression<Func<T, object>>[] properties)
{
    var list = new List<string>();

    foreach (var p in properties)
    {
        if (p.Body is MemberExpression)
        {
            var e = (MemberExpression)p.Body;
            list.Add(((JsonPropertyAttribute)e.Member.GetCustomAttribute(typeof(JsonPropertyAttribute))).PropertyName);
        }
        else
        {
            var e = (MemberExpression)((UnaryExpression)p.Body).Operand;
            list.Add(((JsonPropertyAttribute)e.Member.GetCustomAttribute(typeof(JsonPropertyAttribute))).PropertyName);
        }
    }

    return list;
}
公共静态列表PrintPropertyNames(参数表达式[]属性)
{
var list=新列表();
foreach(属性中的var p)
{
if(p.Body是MemberExpression)
{
var e=(MemberExpression)p.Body;
list.Add(((JsonPropertyAttribute)e.Member.GetCustomAttribute(typeof(JsonPropertyAttribute))).PropertyName);
}
其他的
{
var e=(MemberExpression)((一元表达式)p.Body)。操作数;
list.Add(((JsonPropertyAttribute)e.Member.GetCustomAttribute(typeof(JsonPropertyAttribute))).PropertyName);
}
}
退货清单;
}
我这样称呼它:

Console.WriteLine(string.Join(“,PrintPropertyNames(x=>x.Age,x=>x.Country))

现在,我想修改我的方法定义,使其只接受一个参数,但我不知道如何做

我试过这样做:

公共静态列表PrintPropertyNames2(表达式[]属性)

我这样称呼它:

Console.WriteLine(string.Join(“,PrintPropertyNames2(新表达式[]{x=>x.Age,x=>x.Country}))

我试图将其简化为:

Console.WriteLine(string.Join(“,PrintPropertyNames2(新[]{x=>x.Age,x=>x.Country}))

但是编译器找不到最合适的类型。所以我必须显式地编写类型,它看起来很难看,而且不是我真正想要的。我需要它

在最终版本中,我要做的是:

Console.WriteLine(string.Join(“,PrintPropertyNames(x=>x.Age&&x.Country&&x.Name))(输出应为-
年龄国家/地区名称


我不确定这是否可行,但我想将所有属性放在一个表达式中,并立即获取它们的json属性值。

对于初学者,不能使用
x=>x.Age&&x.Country&&x.Name
-
Age
int
Name
字符串,并且不能将它们与
和&
组合,因此会出现编译器错误。但是我们可以使用
+
代替字符串浓缩,或者返回
新的{x.Name,x.Age,x.Country}
新对象[]{x.Name,x.Age,x.Country}

无论哪种方法,最简单的方法是使用查找所有
MemberAccess
表达式,这些表达式访问输入
Student
中的属性,无论它们位于表达式中的何处:

public class FindPropertiesVisitor : ExpressionVisitor
{
    private readonly Expression parameter;
    public List<string> Names { get; } = new List<string>();

    public FindPropertiesVisitor(Expression parameter) => this.parameter = parameter;

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression == parameter)
        {
            Names.Add(node.Member.GetCustomAttribute<JsonPropertyAttribute>().PropertyName);
        }
        return node;
    }
}

.

对于初学者,您不能使用
x=>x.Age&&x.Country&&x.Name
--
Age
是一个
int
Name
是一个
string
,您不能将它们与
&
组合,因此您将得到一个编译器错误。但是我们可以使用
+
代替字符串浓缩,或者返回
新的{x.Name,x.Age,x.Country}
新对象[]{x.Name,x.Age,x.Country}

无论哪种方法,最简单的方法是使用查找所有
MemberAccess
表达式,这些表达式访问输入
Student
中的属性,无论它们位于表达式中的何处:

public class FindPropertiesVisitor : ExpressionVisitor
{
    private readonly Expression parameter;
    public List<string> Names { get; } = new List<string>();

    public FindPropertiesVisitor(Expression parameter) => this.parameter = parameter;

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression == parameter)
        {
            Names.Add(node.Member.GetCustomAttribute<JsonPropertyAttribute>().PropertyName);
        }
        return node;
    }
}

.

请注意,
x=>x.Age&&x.Country&&x.Name
不是一个有效的表达式,它将编译--
Age
是一个
int
Name
是一个
字符串,你不能将它们与
&
组合注意
x.Age&&x.Country&&x.Name
不是一个有效的表达式,它将编译--
Age
是一个
int
Name
是一个
字符串
,你不能将它们与
&
组合,我认为
FindPropertyNames(x=>新{x.Name,x.Age,x.Country});
一个更好看的用法。@GuruStron Fair point!作为示例添加进来(代码按原样工作)@canton7非常好的答案,谢谢。但是,我必须注意,带plus(最后一个)-
(x=>x.Name+x.Age+x.Country)的语法
如果存在类类型,则不起作用。例如,如果
Age
public CustomAge{get;set;}
,它不起作用。@Axajkamkat在您的特定示例中,它会起作用,因为
string+anything=string
。如果没有将字符串作为前两个内容之一合并在一起,它将不起作用。但是:您必须添加一个空字符串
“”
一开始,我很喜欢Guruston关于匿名对象的建议:没错,我也使用过匿名对象。但是我在我的类中添加了更多属性,其中一个是另一个类属性,正如你所说,它不能与字符串concat一起正常工作。不管怎样,解决方案都非常优雅,谢谢,感谢!我认为
FindPropertyNames(x=>new{x.Name,x.Age,x.Country});
是一个更好看的用法。@GuruStron Fair point!作为示例添加进来(代码按原样工作)@canton7非常好的答案,谢谢。不过,我必须注意,带plus(最后一个)
(x=>x.Name+x.Age+x.Country)的语法
如果存在类类型,则不起作用。例如,如果
Age
public CustomAge{get;set;}
,它不起作用。@Axajkamkat在您的特定示例中,它会起作用,因为
string+anything=string
。如果没有将字符串作为前两个内容之一合并在一起,它将不起作用。但是:您必须添加一个空字符串
“”
一开始,我很喜欢Guruston关于匿名对象的建议:没错,我也使用过匿名对象。但是我在我的类中添加了更多属性,其中一个是另一个类属性,正如你所说,它不能与字符串concat一起正常工作。不管怎样,解决方案都非常优雅,谢谢,谢谢你!
var names = FindPropertyNames<Student>(x => new { x.Name, x.Age, x.Country });
var names = FindPropertyNames<Student>(x => new object[] { x.Name, x.Age, x.Country });
var names = FindPropertyNames<Student>(x => x.Name + x.Age + x.Country);