C# 从基类中的派生类获取属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15834403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 18:06:51  来源:igfitidea点击:

Get properties from derived class in base class

c#oopreflection

提问by Marek M.

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?

在这个例子中 - 我可以在 BaseModel 类中从 ServerItem 类中获取“Name”属性吗?

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

编辑:我正在尝试实现模型验证,如下所述: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...

我想,如果我创建一些包含(几乎)所有验证魔法的基本模型,然后扩展该模型,那就没问题了......

采纳答案by pascalhein

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.

这将为您提供 的所有子类的所有属性BaseClass

回答by Matthew Watson

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

如果您要求派生类必须实现某个方法或属性,则应将该方法或属性作为抽象声明引入基类。

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

例如,对于您的Name财产,您将添加到基类:

public abstract string Name { get; set; }

Then any derived classes mustimplement it, or be abstract classes themselves.

那么任何派生类都必须实现它,或者本身就是抽象类。

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

一旦您将Name属性的抽象版本添加到基类,您将能够在基类中的任何地方访问它,除了基类的构造函数。

回答by General-Doomer

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

从 BaseModel 中扫描所有继承类的程序集并创建字典,如下所示:

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

回答by rr-

If you mustdo 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.

但是,不建议这样做,您很可能应该像 Matthew 所说的那样重新考虑您的设计。

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.

至于不向基类抛出属性——您可以尝试将基类和派生类分离为不相关的对象,并通过构造函数传递它们。

回答by Marek M.

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

好的,我解决的这个问题与这篇文章的作者略有不同: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.

也许它会帮助某人。

回答by user3599701

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());
           }
       }
   }
}

回答by mayank

Another way to solve this issue by create virtualproperty in base class and overrideit 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----            
        }
}