简体   繁体   中英

Is there a way of restricting a foreach loop thorugh a class's properties in C#?

I'm trying to create a class method to fill some flag properties from an integer value containing which flags are true when in binary. The idea of the method is to loop through the flag properties one by one and set them according to the correspondent bit in the integer.

As far as I understand it, using this structure

public void FillFlags( int combinedFlags )
{
    foreach (PropertyInfo prop in GetType().GetProperties() )
    {
         //Do Something
    }
}

will iterate through all of the properties of the instantiated object.

Is it possible to limit the loop to, say, only the properties under a region?

Like:

#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

I'm using Visual Studio 2017 Community edition.

No, regions are not available at runtime.

You can for instance create an attribute and use it on the properties that you want to iterate.

[AttributeUsage(AttributeTargets.Property)]
public class ReflectThisAttribute : Attribute
{
}

And use it like this:

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

Which enables you to:

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

You could also check if it's a 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
    }
}

However!

Since it looks like the FillFlags method is part of the class that you want to change I would recommend that you assign the properties manually in it. The code will become much more readable than trying to use reflection.

Reflection is typically used to generalize solutions. For instance:

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

Usage:

var myEntity = new SomeEntity();

// will set HAS_SOURCE and HAS_SUBJECT to true
myEntity.FillFlags(10);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM