C# 使用表达式从属性获取自定义属性 请考虑下面的代码。我惊讶地发现,输出是双基的,而不是先基后派生的

C# 使用表达式从属性获取自定义属性 请考虑下面的代码。我惊讶地发现,输出是双基的,而不是先基后派生的,c#,C#,我做错什么了吗?可以用不同的方式编写,以基于表达式获取自定义属性。表达式似乎总是使用基类 注释行证明可以通过反射访问自定义属性 public static class Program { private static void Main(string[] args) { Write((Derived data) => data.Code); Write((Base data) => data.Code); // Con

我做错什么了吗?可以用不同的方式编写,以基于表达式获取自定义属性。表达式似乎总是使用基类

注释行证明可以通过反射访问自定义属性

public static class Program
{
    private static void Main(string[] args)
    {
        Write((Derived data) => data.Code);
        Write((Base data) => data.Code);

        // Console.WriteLine(typeof(Derived).GetProperty(nameof(Derived.Code)).GetCustomAttributes<XmlElementAttribute>().First().ElementName);
    }

    private static void Write<T1,T2>(Expression<Func<T1,T2>> expression)
    {
        Console.WriteLine(((MemberExpression) expression.Body).Member.GetCustomAttribute<XmlElementAttribute>().ElementName);
    }
}

public abstract class Base
{
    [XmlElement("Base")]
    public abstract string Code { get; set; }
}

public class Derived : Base
{
    [XmlElement("Derived")]
    public override string Code { get; set; }
}

我真的不明白为什么你的代码不起作用,看起来问题来自lambdas的自动表达式翻译,但这里有一个功能,可以像你所期望的那样,通过做几乎相同的事情,但手动地使用表达式:

private static void Write(Expression expression)
{   
    Console.WriteLine(((MemberExpression)expression.Body).Member.GetCustomAttribute<XmlElementAttribute>().ElementName);
}

private static void Main(string[] args)
{
    Write(Expression.Property(Expression.New(typeof(Derived).GetConstructors()[0]), "Code"));
    Write(Expression.Property(Expression.TypeAs(Expression.New(typeof(Derived).GetConstructors()[0]), typeof(Base)), "Code"));
}

我真的不明白为什么你的代码不起作用,看起来问题来自lambdas的自动表达式翻译,但这里有一个功能,可以像你所期望的那样,通过做几乎相同的事情,但手动地使用表达式:

private static void Write(Expression expression)
{   
    Console.WriteLine(((MemberExpression)expression.Body).Member.GetCustomAttribute<XmlElementAttribute>().ElementName);
}

private static void Main(string[] args)
{
    Write(Expression.Property(Expression.New(typeof(Derived).GetConstructors()[0]), "Code"));
    Write(Expression.Property(Expression.TypeAs(Expression.New(typeof(Derived).GetConstructors()[0]), typeof(Base)), "Code"));
}

我可以证实这种行为。您可以将这两种方法结合使用

    private static void Write<T1, T2>(Expression<Func<T1, T2>> expression)
    {
        var me = ((MemberExpression)expression.Body);

       Console.WriteLine(me.Expression.Type.GetProperty(me.Member.Name)
        .GetCustomAttributes<XmlElementAttribute>().First().ElementName);
    }

看起来GetCustToAttribute正在访问BaseType,而GetCustomAttributes正在返回类层次结构中的所有属性。使用First,您只需访问顶部声明。

我可以确认此行为。您可以将这两种方法结合使用

    private static void Write<T1, T2>(Expression<Func<T1, T2>> expression)
    {
        var me = ((MemberExpression)expression.Body);

       Console.WriteLine(me.Expression.Type.GetProperty(me.Member.Name)
        .GetCustomAttributes<XmlElementAttribute>().First().ElementName);
    }

看起来GetCustToAttribute正在访问BaseType,而GetCustomAttributes正在返回类层次结构中的所有属性。使用First,您只需访问顶部声明。

我看您是从其他地方复制粘贴的吗?而且里面可能有控制字符。我只是像往常一样从Visual Studio复制粘贴,我不明白这次为什么不起作用,只是在没有复制粘贴的情况下重写了行,它就起作用了,谢谢你给我这个想法。尽管你的解决方案可能起作用,但它太复杂了,达不到目的。我想要一些优雅的东西,也想要一些可以随时重构的东西。您的解决方案提供了类似于编译器首先应该做的事情。是的,我知道这段代码的问题是什么:/我不认为有办法让它按您希望的方式工作,因为您所做的应该在我看来是可行的。也许您应该试着让Microsoft看到这个问题。可以肯定的是,我不能为你做更多的事情。在我看来,你是从别处复制粘贴的吗?而且里面可能有控制字符。我只是像往常一样从Visual Studio复制粘贴,我不明白这次为什么不起作用,只是在没有复制粘贴的情况下重写了行,它就起作用了,谢谢你给我这个想法。尽管你的解决方案可能起作用,但它太复杂了,达不到目的。我想要一些优雅的东西,也想要一些可以随时重构的东西。您的解决方案提供了类似于编译器首先应该做的事情。是的,我知道这段代码的问题是什么:/我不认为有办法让它按您希望的方式工作,因为您所做的应该在我看来是可行的。也许您应该试着让Microsoft看到这个问题。可以肯定的是,我不能为您做更多的事情。请使用GetCustomAttributefalse重载,以确保将inherited设置为false。然后检查成员的类型,它真的是“派生”类型吗。您的“成员”必须与注释行中的PropertyInfo相同。使用GetCustomAttributefalse不会更改任何内容。两种情况下的成员似乎都引用了Base。请使用GetCustomAttributefalse重载,以确保将inherited设置为false。然后检查成员的类型,它真的是“派生”类型吗。您的“成员”必须与注释行中的PropertyInfo相同。使用GetCustomAttributefalse不会更改任何内容。这两种情况下的成员似乎都是参考基础。万岁!这似乎奏效了。或者,你的其他建议也有帮助。不需要调用复数版本,而是改为使用GetCustomAttributefalse。这确实会起作用,很好。但是仍然存在一个问题,如果给定属性具有多个相同类型的属性,那么它可能并不总是返回您要查找的属性。万岁!这似乎奏效了。或者,你的其他建议也有帮助。不需要调用复数版本,而是改为使用GetCustomAttributefalse。这确实会起作用,很好。但是仍然存在一个问题,如果给定属性具有多个相同类型的属性,那么它可能并不总是返回您要查找的属性。