Marek M.
Marek M.

Reputation: 3951

Get properties from derived class in base class

How do I get properties from derived class in base class?

Base class:

public abstract class BaseModel {
    protected static readonly Dictionary<string, Func<BaseModel, object>>
            _propertyGetters = typeof(BaseModel).GetProperties().Where(p => _getValidations(p).Length != 0).ToDictionary(p => p.Name, p => _getValueGetter(p));
}

Derived classes:

public class ServerItem : BaseModel, IDataErrorInfo {
    [Required(ErrorMessage = "Field name is required.")]
    public string Name { get; set; }
}

public class OtherServerItem : BaseModel, IDataErrorInfo {
    [Required(ErrorMessage = "Field name is required.")]
    public string OtherName { get; set; }

    [Required(ErrorMessage = "Field SomethingThatIsOnlyHereis required.")]
    public string SomethingThatIsOnlyHere{ get; set; }
}

In this example - can I get the "Name" property from ServerItem class while in BaseModel class?

EDIT: I'm trying to implement model validation, as described here: http://weblogs.asp.net/marianor/archive/2009/04/17/wpf-validation-with-attributes-and-idataerrorinfo-interface-in-mvvm.aspx

I figured that if I create some base model with (almost) all of the validation magic in it, and then extend that model, it will be okay...

Upvotes: 12

Views: 38185

Answers (7)

mayank
mayank

Reputation: 2665

Another way to solve this issue by create virtual property in base class and override it to derived class.

public class Employee
{
    public virtual string Name {get; set;}
}

public class GeneralStaff
{
    public override string Name {get; set;}
}

class Program
{
        static void Main(string[] args)
        {
            Employee emp = new GeneralStaff();
            emp.Name = "Abc Xyz";
            //---- More code follows----            
        }
}

Upvotes: 3

user3599701
user3599701

Reputation: 27

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TESTNEW
{
   public abstract class BusinessStructure
    {
       public BusinessStructure()
       { }

       public string Name { get; set; }
   public string[] PropertyNames{
       get
       { 
                System.Reflection.PropertyInfo[] Pr;
                System.Type _type = this.GetType();
                Pr = _type.GetProperties();
                string[] ReturnValue = new string[Pr.Length];
                for (int a = 0; a <= Pr.Length - 1; a++)
                {
                    ReturnValue[a] = Pr[a].Name;
                }
                return ReturnValue;
       }
   }

}


public class MyCLS : BusinessStructure
   {
       public MyCLS() { }
       public int ID { get; set; }
       public string Value { get; set; }


   }
   public class Test
   {
       void Test()
       {
           MyCLS Cls = new MyCLS();
           string[] s = Cls.PropertyNames;
           for (int a = 0; a <= s.Length - 1; a++)
           {
            System.Windows.Forms.MessageBox.Show(s[a].ToString());
           }
       }
   }
}

Upvotes: 0

Marek M.
Marek M.

Reputation: 3951

Okay, I solved this problem slightly different than the author of this post: http://weblogs.asp.net/marianor/archive/2009/04/17/wpf-validation-with-attributes-and-idataerrorinfo-interface-in-mvvm.aspx

public abstract class BaseModel : IDataErrorInfo {
    protected Type _type;
    protected readonly Dictionary<string, ValidationAttribute[]> _validators;
    protected readonly Dictionary<string, PropertyInfo> _properties;

    public BaseModel() {
        _type = this.GetType();
        _properties = _type.GetProperties().ToDictionary(p => p.Name, p => p);
        _validators = _properties.Where(p => _getValidations(p.Value).Length != 0).ToDictionary(p => p.Value.Name, p => _getValidations(p.Value));
    }

    protected ValidationAttribute[] _getValidations(PropertyInfo property) {
        return (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true);
    }

    public string this[string columnName] {
        get {
            if (_properties.ContainsKey(columnName)) {
                var value = _properties[columnName].GetValue(this, null);
                var errors = _validators[columnName].Where(v => !v.IsValid(value)).Select(v => v.ErrorMessage).ToArray();
                return string.Join(Environment.NewLine, errors);
            }

            return string.Empty;
        }
    }

    public string Error {
        get { throw new NotImplementedException(); }
    }
}

Maybe it will help somebody.

Upvotes: 1

rr-
rr-

Reputation: 14811

If you must do literally fetch property of derived class from within base class, you can use Reflection, for example - like this...

using System;
public class BaseModel
{
    public string getName()
    {
        return (string) this.GetType().GetProperty("Name").GetValue(this, null);
    }
}

public class SubModel : BaseModel
{
    public string Name { get; set; }
}

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            SubModel b = new SubModel();
            b.Name = "hello";
            System.Console.Out.WriteLine(b.getName()); //prints hello
        }
    }
}

This is not recommended, though, and you most probably should rethink your design like Matthew said.

As for not throwing properties to your base classes -- you can try to decouple base and deriving classes into unrelated objects and pass them via constructors.

Upvotes: 8

pascalhein
pascalhein

Reputation: 5846

If both classes are in the same assembly, you can try this:

Assembly
    .GetAssembly(typeof(BaseClass))
    .GetTypes()
    .Where(t => t.IsSubclassOf(typeof(BaseClass))
    .SelectMany(t => t.GetProperties());

This will give you all the properties of all the subclasses of BaseClass.

Upvotes: 11

General-Doomer
General-Doomer

Reputation: 2761

Scan your assembly for all inherited classes from BaseModel and create dictionary like this:

Dictionary<Type, Dictionary<string, Func<BaseModel, object>>>

Upvotes: 0

Matthew Watson
Matthew Watson

Reputation: 109547

If you require that a derived class must implement a method or property, you should introduce that method or property into the base class as an abstract declaration.

For example, for your Name property, you would add to the base class:

public abstract string Name { get; set; }

Then any derived classes must implement it, or be abstract classes themselves.

Once you have added the abstract version of the Name property to the base class, you will be able to access it in the base class anywhere except in the base class's constructor.

Upvotes: 8

Related Questions