2

以下の基本、中間、および派生クラスがあります::

public class Base
{
    [DataMemberAttribute()]
    public int ValueBase { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreBase { get; set; }
}

public class Middle : Base
{
    [DataMemberAttribute()]
    public int ValueMiddle { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreMiddle { get; set; }
}

public class MostDerived : Middle
{
    [DataMemberAttribute()]
    public int ValueMostDerived { get; set; }

    [IgnoreForAllAttribute("Param1", "Param2")]
    public int IgnoreMostDerived { get; set; }
}

型を指定する関数が必要です。ベースを除く階層内のすべてのクラスの DataMemberAttribute 属性を返す必要があります。

さらに、グラフ内のすべてのクラスについて、すべての IgnoreForAllAttribute 属性を無視する必要があります。

var derivedObject = new MostDerived();
var attributes = MyShinyAttributeFunction(derivedObject.GetType());
// returns [] { ValueMostDerived, ValueMiddle }
4

4 に答える 4

6

DateMemberAttribute と IgnoreForAllAttribute が相互に排他的であると想定する LINQ サンプルを次に示します。

IEnumerable<PropertyInfo> MyProperties(object o)
{
   o.GetType().GetProperties()
    .Where(p => !(p.DeclaringType is Base))
    .Where(p => p.GetCustomAttributes(false).Any(a => a is DataMemberAttribute)
}

そして、属性が相互に排他的ではないと仮定したサンプル

IEnumerable<PropertyInfo> MyProperties(object o)
{
   o.GetType().GetProperties()
    .Where(p => !(p.DeclaringType is Base))
    .Where(p => 
       { 
          var attributes = p.GetCustomAttributes(false);
          return attributes.Any(a => a is DataMemberAttribute)
             && !attributes.Any(a => a is IgnoreForAllAttribute);
       }
}
于 2012-10-01T04:59:25.467 に答える
3
var properties = new List<PropertyInfo>();

GetProps(typeof(MostDerived), properties);

GetProps は、宣言している型のプロパティを取得し、階層内の次の型に対して自分自身を呼び出す再帰関数です。「ベース」に到達すると停止します

private static void GetProps(Type T, List<PropertyInfo> Properties)
{
  if (T != typeof(Base))
  {
    var pis = T.GetProperties();

    foreach (var pi in pis)
    {
      if (pi.DeclaringType == T &&
        pi.GetCustomAttribute<DataMemberAttribute>() != null &&
        pi.GetCustomAttribute<IgnoreForAllAttribute>() == null)
      {
        Properties.Add(pi);
      }
    }

    GetProps(T.BaseType, Properties);

  }
}

プロパティ リストには、DataMemberAttribute を持ち、IgnoreForAllAttribute を持たないプロパティが含まれます。

于 2012-10-01T04:30:08.373 に答える
1

次の関数を使用して、必要な結果を得ることができます: propertyNames で、必要なプロパティを取得します。

使用法:

List<string> propertyNames = new List<string>();
List<string> basePropertyNames = new List<string>();
MyShinyAttributeFunction(derivedObject.GetType(), ref propertyNames, ref basePropertyNames);

関数:

void MyShinyAttributeFunction(Type type, ref List<string> propertyNames, ref List<string> basePropertyNames)
{
    if (type == null)
        return;

    MyShinyAttributeFunction(type.BaseType, ref propertyNames, ref basePropertyNames);

    foreach (var property in type.GetProperties())
    {
        foreach (object customAttr in property.GetCustomAttributes(false))
        {
            if (customAttr is DataMemberAttribute)
            {
                if (type.BaseType.Name.Equals("Object"))
                {
                    DataMemberAttribute attribute = (DataMemberAttribute)customAttr;
                    if (!basePropertyNames.Contains(property.Name))
                        basePropertyNames.Add(property.Name);
                }
                else
                {
                    DataMemberAttribute attribute = (DataMemberAttribute)customAttr;
                    if (!propertyNames.Contains(property.Name) && !basePropertyNames.Contains(property.Name))
                        propertyNames.Add(property.Name);
                }
            }
        }
    }
}
于 2012-10-01T04:17:25.097 に答える
0

以下を利用する必要があります。

BaseType が存在しない場合に停止する再帰関数がうまくいくはずです。

于 2012-10-01T04:18:08.580 に答える