Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.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检索属性描述的写扩展方法#_C#_C# 4.0_C# 3.0 - Fatal编程技术网

C# 使用c检索属性描述的写扩展方法#

C# 使用c检索属性描述的写扩展方法#,c#,c#-4.0,c#-3.0,C#,C# 4.0,C# 3.0,我有以下课程 public class Device { [XmlElement("MobileDeviceType")] public string DeviceType { get; set; } } 我需要一个名为“GetXElementName()”的扩展方法,我需要使用下面的方法 string propertyDescription = (new Device()).DeviceType.GetXElementName(); // this shoud return

我有以下课程

public class Device
{
    [XmlElement("MobileDeviceType")]
    public string DeviceType { get; set; }
}
我需要一个名为“GetXElementName()”的扩展方法,我需要使用下面的方法

string propertyDescription = (new Device()).DeviceType.GetXElementName(); // this shoud return "MobileDeviceType"
例如

public static class ExtensionMethods
{
    public static string GetXElementName<T>(this T source)
    {
        PropertyInfo prop = source.GetType().GetProperty(source.ToString());
        string desc = prop.Name;
        object[] attrs = prop.GetCustomAttributes(true);
        object attr = attrs[0];
        XmlElementAttribute descAttr = attr as XmlElementAttribute;
        if (descAttr != null)
        {
            desc = descAttr.ElementName;
        }

        return desc;
    }
}
公共静态类扩展方法
{
公共静态字符串GetXElementName(此T源)
{
PropertyInfo prop=source.GetType().GetProperty(source.ToString());
string desc=prop.Name;
object[]attrs=prop.GetCustomAttributes(true);
对象属性=属性[0];
XmlElementAttribute descAttr=attr作为XmlElementAttribute;
if(descAttr!=null)
{
desc=descAttr.ElementName;
}
返回描述;
}
}

我可以知道我应该如何修改方法体以使用“GetXElementName()”方法来使用,就像我上面解释的那样。

您需要使用表达式来实现这一点,因为您需要知道成员,而不是值

public static class Extensions
{
    public static string GetXmlElementName<T, TProperty>(this T obj, Expression<Func<T, TProperty>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
            return string.Empty;

        var xmlElementAttribute = memberExpression.Member.GetCustomAttribute<XmlElementAttribute>();
        if (xmlElementAttribute == null)
            return string.Empty;

        return xmlElementAttribute.ElementName;
    }
}
编辑:另一个版本,没有对象实例(请参见注释)

我想最优雅的方法是使用泛型方法创建泛型类,因此您可以通过只指定
T
类型参数来调用它(
TProperty
是隐式获取的)

公共类GetXmlElementName
{
来自(表达式)的公共静态字符串
{
var memberExpression=expression.Body作为memberExpression;
if(memberExpression==null)
返回字符串。空;
var xmlElementAttribute=memberExpression.Member.GetCustomAttribute();
如果(xmlElementAttribute==null)
返回字符串。空;
返回xmlElementAttribute.ElementName;
}
}
用法:

public class MyClass
{
    [XmlElement(ElementName = "Test")]
    public string MyProperty { get; set; }
}

new MyClass().GetXmlElementName(x => x.MyProperty) // output "Test"
GetXmlElementName<MyClass>.From(x => x.MyProperty) // output "Test"
GetXmlElementName.From(x=>x.MyProperty)//输出“Test”

您需要使用表达式来实现这一点,因为您需要知道成员,而不是值

public static class Extensions
{
    public static string GetXmlElementName<T, TProperty>(this T obj, Expression<Func<T, TProperty>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
            return string.Empty;

        var xmlElementAttribute = memberExpression.Member.GetCustomAttribute<XmlElementAttribute>();
        if (xmlElementAttribute == null)
            return string.Empty;

        return xmlElementAttribute.ElementName;
    }
}
编辑:另一个版本,没有对象实例(请参见注释)

我想最优雅的方法是使用泛型方法创建泛型类,因此您可以通过只指定
T
类型参数来调用它(
TProperty
是隐式获取的)

公共类GetXmlElementName
{
来自(表达式)的公共静态字符串
{
var memberExpression=expression.Body作为memberExpression;
if(memberExpression==null)
返回字符串。空;
var xmlElementAttribute=memberExpression.Member.GetCustomAttribute();
如果(xmlElementAttribute==null)
返回字符串。空;
返回xmlElementAttribute.ElementName;
}
}
用法:

public class MyClass
{
    [XmlElement(ElementName = "Test")]
    public string MyProperty { get; set; }
}

new MyClass().GetXmlElementName(x => x.MyProperty) // output "Test"
GetXmlElementName<MyClass>.From(x => x.MyProperty) // output "Test"
GetXmlElementName.From(x=>x.MyProperty)//输出“Test”


好吧,它不是按预期工作吗?您会遇到什么错误?为了安全起见,您可能希望遍历所有属性,而不仅仅是第一个属性,当您找到一个
xmlementattribute
时,只需返回
ElementName
。顺便说一句:要通过反射获取属性,您需要属性名称,而不是它的字符串表示。因此,
source.ToString
没有多大意义。在您的情况下,
source.ToString
将只返回
设备
设备类型
的值,而不仅仅是
设备类型
。你的方法到底应该做什么?它无论如何都不会起作用
DeviceType.GetXElementName()
将尝试对该属性的getter的结果而不是属性本身运行此函数。您需要一个类似
new Device())的调用@nyrguds,或者像我的回答一样,通过expressionsWell,它不是如预期的那样工作吗?您会遇到什么错误?为了安全起见,您可能希望遍历所有属性,而不仅仅是第一个属性,当您找到一个
xmlementattribute
时,只需返回
ElementName
。顺便说一句:要通过反射获取属性,您需要属性名称,而不是它的字符串表示。因此,
source.ToString
没有多大意义。在您的情况下,
source.ToString
将只返回
设备
设备类型
的值,而不仅仅是
设备类型
。你的方法到底应该做什么?它无论如何都不会起作用
DeviceType.GetXElementName()
将尝试对该属性的getter的结果而不是属性本身运行此函数。您需要一个类似
new Device())的调用@nyrguds,或者像我的回答一样,通过表达式这个版本允许强类型属性。我更喜欢这种方法。显然,这是最好的答案,是的。好极了。对于仍然停留在v3.5中的人来说,只有“GetCustomAttributes”,复数形式,并且它获取要查找的类型作为参数,但是除了需要数组长度检查而不是空检查之外,它的工作原理完全相同。我唯一的挑剔是它仍然需要伪对象。。。有没有办法不用它就能做到这一点?(是的,我知道是这样问的,但仍然很愚蠢)似乎可以不用,将签名更改为
getxmlementname(Expression-Expression)
并调用
getxmlementname(x=>x.MyProperty)在我的示例中,使用
Object
解决了这个问题,但是,是的,您也可以将它嵌入一个接受显式泛型类型的帮助器类中。事实上,我对此做了一些实验,最终得到了一个完全通用的属性属性获取系统,在这个系统中,您甚至可以指定要从中获取的属性类和属性:
public static class PropertyCustomAttributeUtil where TAttr:attribute
->
public static TRes GetValue(Expression,Expression attrExpression)
。这个东西很有趣:)这个版本允许强类型属性。我更喜欢这种方法。显然,这是最好的答案,是的。好极了。对于仍停留在v3.5中的用户,只有