简体   繁体   中英

How to define a static method in a superclass to get the properties of a subclass using reflection?

I have a class, BaseClass , that has a GetPropertyByDataMemberName method. This method uses reflection to get the property that has a DataMemberAttribute with a specified name. I want to define it as a static method in BaseClass so I don't have to define it in each subclass.

Problem is, since this method uses reflection to look up the properties, I need to get the current Type somehow in order to call GetProperties . Since it's a static method, I can't call GetType , so I'm at a loss of how to do that!

abstract class BaseClass
{
    [DataMember(Name = "p1")]
    public int PropertyOne{ get; set; }

    public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
    {
        return GetType() // argh! can't call this statically!
            .GetProperties()
            .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
            .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
    }
}

Why not make it non-static? Well, let's say I have a subclass like this:

class SubClassOne : BaseClass
{
    [DataMember(Name = "p2")]
    public string PropertyTwo { get; set; }
}

I want to be able to do something like this:

static void Main(string[] args)
{
    // print property names
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p1").Name);   // should work
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p2").Name);   // should not work
    Console.WriteLine(SubClassOne.GetPropertyByDataMemberName("p1").Name); // should work
    Console.WriteLine(SubClassOne.GetPropertyByDataMemberName("p2").Name); // should work
}

I've tried making GetPropertyByDataMemberName use typeof(BaseClass) , but that only gets the properties of BaseClass , not any of the subclasses.

public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
{
    return typeof(BaseClass)
        .GetProperties() // only gets properties of BaseClass
        .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
        .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
}

So, how to do this?

You can use generics to achieve this:

public static PropertyInfo GetPropertyByDataMemberName<T>(string dataMemberName)
    where T : BaseClass
{
    return typeof(T)
        .GetProperties()
        .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
        .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
}

// Shortcut overload for properties on BaseClass.
public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
{
    return GetPropertyByDataMemberName<BaseClass>(dataMemberName);
}

You would call it like this:

static void Main(string[] args)
{
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p1").Name);   // should work
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p2").Name);   // should not work
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName<SubClassOne>("p1").Name); // should work
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName<SubClassOne>("p2").Name); // should work
}

Try this:

public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
{
    var st = new StackTrace();

    var type = ((System.Reflection.MemberInfo)(st.GetFrame(0).GetMethod())).ReflectedType;
    return type // argh! can't call this statically!
        .GetProperties()
        .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
        .Single(z => ((DataMemberAttribute)Attribute
            .GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM