簡體   English   中英

從基類中的派生類獲取屬性

[英]Get properties from derived class in 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));
}

派生類:

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

在這個例子中 - 我可以在BaseModel類中從ServerItem類獲取“Name”屬性嗎?

編輯:我正在嘗試實現模型驗證,如下所述: http//weblogs.asp.net/marianor/archive/2009/04/17/wpf-validation-with-attributes-and-idataerrorinfo-interface-in -mvvm.aspx

我想如果我用(幾乎)所有的驗證魔法創建一些基礎模型,然后擴展該模型,它就可以了...

如果要求派生類必須實現方法或屬性,則應將該方法或屬性作為抽象聲明引入基類。

例如,對於Name屬性,您將添加到基類:

public abstract string Name { get; set; }

然后,任何派生類都必須實現它,或者是抽象類本身。

Name屬性的抽象版本添加到基類后, 除了基類的構造函數之外 ,您將能夠在基類中訪問它。

如果你必須從基類中逐字地獲取派生類的屬性,你可以使用Reflection,例如 - 像這樣......

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
        }
    }
}

不過這是不推薦的,你很可能應該重新考慮你的設計,就像馬修所說的那樣。

至於不向基類拋出屬性 - 您可以嘗試將基類和派生類分離為不相關的對象,並通過構造函數傳遞它們。

如果兩個類都在同一個程序集中,您可以嘗試這樣做:

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

這將為您提供BaseClass所有子類的所有屬性。

好的,我解決了這個問題與這篇文章的作者略有不同: 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(); }
    }
}

也許它會對某人有所幫助。

從BaseModel掃描程序集中所有繼承的類,並像這樣創建字典:

Dictionary<Type, Dictionary<string, Func<BaseModel, object>>>
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());
           }
       }
   }
}

通過在基類中創建虛擬屬性並將其覆蓋到派生類來解決此問題的另一種方法。

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----            
        }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM