33

Hi i'm working in a class library using C#, and i have some classes with some properties.

I just wanna know if i can add something to exclude some properties form the getType().GetProperties().

An example of what i want:

class Test
{
    public string one { get; set; }
    public string two {get ; set;}
}

and if i do this:

static void Main(string[] args)
{

       Test t = new Test();
       Type ty = t.GetType();
       PropertyInfo[] pinfo = ty.GetProperties();

       foreach (PropertyInfo p in pinfo)
       {
           Console.WriteLine(p.Name);
       }
  }

i want the output be something like this:

one

or just one of the properties.

Is possible to do something like that? i don't know if there some kind of modifiers or annotations in C#, that allow me to do what i want.

Thanks.

Liam
  • 27,717
  • 28
  • 128
  • 190
danielgomezdidier
  • 381
  • 2
  • 5
  • 9
  • Just out of curiosity, why would you want to hide a public property from Reflection? – Justin Niessner Jan 12 '10 at 19:45
  • 1
    I just need to build some string representation of pairs key/value of some classes For the sample the string representation i need is: one=valueOfOne And so for some properties, but i have some properties that i don't need in the string representation. – danielgomezdidier Jan 12 '10 at 20:24

7 Answers7

46

Extension methods and attributes will help you:

public class SkipPropertyAttribute : Attribute
{
}

public static class TypeExtensions
{
    public static PropertyInfo[] GetFilteredProperties(this Type type)
    {
        return type.GetProperties().Where(pi => pi.GetCustomAttributes(typeof(SkipPropertyAttribute), true).Length == 0).ToArray();
    }       
}

public class Test
{
    public string One { get; set; }

    [SkipProperty]
    public string Two { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var t = new Test();
        Type ty = t.GetType();

        PropertyInfo[] pinfo = ty.GetFilteredProperties();
        foreach (PropertyInfo p in pinfo)
        {
            Console.WriteLine(p.Name);
        }

        Console.ReadKey();
    }
}

UPDATE:

Little more elegant implementation of the GetFilteredProperties (thanks to Marc Gravell):

public static class TypeExtensions
{
    public static PropertyInfo[] GetFilteredProperties(this Type type)
    {
        return type.GetProperties()
              .Where(pi => !Attribute.IsDefined(pi, typeof(SkipPropertyAttribute)))
              .ToArray();
    }
}
Liam
  • 27,717
  • 28
  • 128
  • 190
bniwredyc
  • 8,649
  • 1
  • 39
  • 52
  • 3
    For info, `Attribute.IsDefined` may be more efficient, but a good answer. – Marc Gravell Jan 12 '10 at 21:22
  • in .netcore need to change to this `return type.GetProperties().Where(pi => !pi.IsDefined(typeof(SkipPropertyAttribute))).ToArray();` – Mohammad Hossein Amri Apr 12 '17 at 08:57
  • Would be nice if the answer could be restructured to have the more elegant solution first. I implemented the first solution before I saw the more elegant version lol. – Chad Aug 24 '19 at 00:45
7

You could put a custom attribute on your type.

public class DoNotIncludeAttribute : Attribute
{
}

public static class ExtensionsOfPropertyInfo
{
    public static IEnumerable<T> GetAttributes<T>(this PropertyInfo propertyInfo) where T : Attribute
    {
        return propertyInfo.GetCustomAttributes(typeof(T), true).Cast<T>();
    }
    public static bool IsMarkedWith<T>(this PropertyInfo propertyInfo) where T : Attribute
    {
        return property.GetAttributes<T>().Any();
    }
}
public class Test
{
    public string One { get; set; }

    [DoNotInclude]
    public string Two { get; set; }
}

Then, in your runtime, you can search for properties that are not hidden.

foreach (var property in properties.Where(p => !p.IsMarkedWith<DoNotIncludeAttribute>())
{
    // do something...
}

It won't be really hidden, but it wouldn't show up in the enumeration.

Jarrett Meyer
  • 19,333
  • 6
  • 58
  • 52
1

I'm not sure what the domain is here, so I'm going out on a limb...

Usually what you want to do is use Attributes to tag the properties to include in your metadata searching, not the other way around.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
0

With the PropertyInfo object you can examine the GetCustomAttributes of the property. So you could add attributes to your properties when you declare them, and then when you are reflecting against the properties, you can choose only the properties that are marked with the attributes you desire.

Of course if you are actually wanting to somehow prevent someone from reflectively getting your properties, this is not the solution you want.

Edit: I'm sorry you want GetCustomAttributes, fixed. See this: http://msdn.microsoft.com/en-us/library/kff8s254.aspx

AaronLS
  • 37,329
  • 20
  • 143
  • 202
0

I don't think you can do this directly, but you could add your own custom attributes and filter them out yourself...

Jerod Venema
  • 44,124
  • 5
  • 66
  • 109
0

Although I prefer, and am going to use, the attribute way, I did get this working in a different way that might help the OP.

Here's an example:

PropertyInfo[] properties = record.GetType().GetProperties().Where(p => !"Description".Equals(p.Name)).ToArray();

This will exclude any properties that are named "Description". If you're not able to change the class that contains the properties this could be an option. Again, I prefer the attribute way mentioned above.

adprocas
  • 1,863
  • 1
  • 14
  • 31
0

Another option is adding inheritance. You keep on your base class only what you want to get.

class TestBase
{
    public string one { get; set; }
}

class Test : TestBase
{
    public string two { get; set; }
}


TestBase t = new TestBase();
Type ty = t.GetType();
PropertyInfo[] pinfo = ty.GetProperties();

foreach (PropertyInfo p in pinfo)
{
    Console.WriteLine(p.Name);
}

This prints:

one
LucaSC
  • 722
  • 1
  • 10
  • 19