Reputation: 3951
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
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
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
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
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
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
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
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