有没有办法通过 C# 中的类的属性来限制 foreach 循环?

Raf*_*oto 0 c# loops properties

我正在尝试创建一个类方法来从一个整数值填充一些标志属性,其中包含哪些标志在二进制时为真。该方法的思想是将标志属性一一循环,并根据整数中的对应位进行设置。

据我了解,使用这种结构

public void FillFlags( int combinedFlags )
{
    foreach (PropertyInfo prop in GetType().GetProperties() )
    {
         //Do Something
    }
}
Run Code Online (Sandbox Code Playgroud)

将遍历实例化对象的所有属性。

是否可以将循环限制为仅区域下的属性?

喜欢:

#region Flags
public bool HAS_POSITION { get; set; }
public bool HAS_SOURCE { get; set; }
public bool HAS_DESTINATION { get; set; }
public bool HAS_SUBJECT { get; set; }
#endregion
Run Code Online (Sandbox Code Playgroud)

我正在使用 Visual Studio 2017 社区版。

jga*_*fin 5

不,区域在运行时不可用。

例如,您可以创建一个属性并在要迭代的属性上使用它。

[AttributeUsage(AttributeTargets.Property)]
public class ReflectThisAttribute : Attribute
{
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

[ReflectThis]
public bool HAS_POSITION { get; set; }

[ReflectThis]
public bool HAS_SOURCE { get; set; }

[ReflectThis]
public bool HAS_DESTINATION { get; set; }

[ReflectThis]
public bool HAS_SUBJECT { get; set; }
Run Code Online (Sandbox Code Playgroud)

这使您能够:

public void FillFlags( int combinedFlags )
{
    foreach (PropertyInfo prop in GetType().GetProperties() )
    {
         if (prop.GetCustomAttribute<ReflectThisAttribute> == null)
             continue;

         // Only get here if the property have the attribute
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以检查它是否是bool

public void FillFlags( int combinedFlags )
{
    foreach (PropertyInfo prop in GetType().GetProperties() )
    {
         if (prop.PropertyType != typeof(bool))
             continue;

         // Only get here if the property is a bool
    }
}
Run Code Online (Sandbox Code Playgroud)

然而!

由于该FillFlags方法看起来像是您要更改的类的一部分,因此我建议您在其中手动分配属性。与尝试使用反射相比,代码将变得更具可读性。

反射通常用于概括解决方案。例如:

[AttributeUsage(AttributeTargets.Property)]
public class FlagValueAttribute : Attribute
{
     public FlagValueAttribute (int value)
     {
         Value = value;
     }

     public int Value{get;set}
}

public class SomeEntity
{

    [FlagValue(1)]
    public bool HAS_POSITION { get; set; }

    [FlagValue(2)]
    public bool HAS_SOURCE { get; set; }

    [FlagValue(4)]
    public bool HAS_DESTINATION { get; set; }

    [FlagValue(8)]
    public bool HAS_SUBJECT { get; set; }
}

public static class EntityExtensions
{

    public static void FillFlags(this object instance, int combinedFlags )
    {
        foreach (PropertyInfo prop in instance.GetType().GetProperties() )
        {
             var attr = prop.GetCustomAttribute<FlagValueAttribute>();
             if (attr == null)
                 continue;

             if ((attr.Value & combinedFlags) != 0)
                 prop.SetValue(instance, true);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

var myEntity = new SomeEntity();

// will set HAS_SOURCE and HAS_SUBJECT to true
myEntity.FillFlags(10);
Run Code Online (Sandbox Code Playgroud)