Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get `Type` of subclass from base class

I have an abstract base class where I would like to implement a method that would retrieve an attribute property of the inheriting class. Something like this...

public abstract class MongoEntityBase : IMongoEntity {

    public virtual object GetAttributeValue<T>(string propertyName) where T : Attribute {
        var attribute = (T)typeof(this).GetCustomAttribute(typeof(T));
        return attribute != null ? attribute.GetType().GetProperty(propertyName).GetValue(attribute, null) : null;
    }
}

And Implemented like so...

[MongoDatabaseName("robotdog")]
[MongoCollectionName("users")]
public class User : MonogoEntityBase {
    public ObjectId Id { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    public string email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string password { get; set; }

    public IEnumerable<Movie> movies { get; set; }
}

But of course with the above code the GetCustomAttribute() is not an available method because this isn't a concrete class.

What does typeof(this) in the abstract class need to change to in order to have access to the inheriting class? Or is this not good practice and should I implement the method in the inheriting class altogether?

like image 899
bflemi3 Avatar asked Apr 28 '13 14:04

bflemi3


2 Answers

You should use this.GetType(). That will provide you with the actual concrete type of the instance.

So in this case:

public virtual object GetAttributeValue<T>(string propertyName) where T : Attribute {
    var attribute = this.GetType().GetCustomAttribute(typeof(T));
    return attribute != null ? attribute.GetType().GetProperty(propertyName).GetValue(attribute, null) : null;
}

Note, that it will return the top-most class. That is, if you had:

public class AdministrativeUser : User
{

}

public class User : MongoEntityBase
{

}

Then this.GetType() will return AdministrativeUser.


Also, this means that you could implement the GetAttributeValue method outside of the abstract base class. You wouldn't require implementers to inherit from MongoEntityBase.

public static class MongoEntityHelper
{
    public static object GetAttributeValue<T>(IMongoEntity entity, string propertyName) where T : Attribute 
    {
        var attribute = (T)entity.GetType().GetCustomAttribute(typeof(T));
        return attribute != null ? attribute.GetType().GetProperty(propertyName).GetValue(attribute, null) : null;
    }
}

(could also implement it as an extension method if you wish to)

like image 56
Chris Sinclair Avatar answered Oct 17 '22 07:10

Chris Sinclair


typeof(this) won't compile.

What you're searching for is this.GetType().

like image 31
LightStriker Avatar answered Oct 17 '22 06:10

LightStriker