1

What I'm trying to do is get the attribute from a property within my class using a custom attribute. The custom attribute in question looks like this:

[System.AttributeUsage(System.AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class PrimarykeyAttribute : Attribute
    {
        bool key;
        public PrimarykeyAttribute(bool key)
            {
                this.key = key;
            }

        public bool GetKey()
        {
            return key;
        }
    }

And when applied to a property in a class it would look like this:

public class Company
    {
        [Primarykey(true)]
        public int CompanyID { get; set; }
        public string Name { get; set; }
        public string Adress { get; set; }

Now what I'm trying to do is reading through all the properties within this class and checking whether they have any attributes and if so do something depending on the attribute, ergo in this case, ignore this property when making a generated SQL Query for the sake of automated ID's. I've tried multiple things from questions already asked here but none worked for me, usually returning an arror along the lines of not working for a boolean. What I've already tried is this:

public static class AttributeHelper
    {
        public static object GetPropertyAttributes(PropertyInfo prop, string attributeName)
        {
            // look for an attribute that takes one constructor argument
            foreach (CustomAttributeData attribData in prop.GetCustomAttributesData())
            {
                string typeName = attribData.Constructor.DeclaringType.Name;
                if (attribData.ConstructorArguments.Count == 1 &&
                    (typeName == attributeName || typeName == attributeName + "Attribute"))
                {
                    return attribData.ConstructorArguments[0].Value;
                }
            }
            return null;

The issue with this is that it is hard coded in the argument it will take, whilst I need it to be dynamic, not checking simply 1 property.

  • Does this answer your question? [Check if property has attribute](https://stackoverflow.com/questions/2051065/check-if-property-has-attribute) – Connor Stoop Mar 29 '21 at 11:27
  • *"I've tried multiple things from questions already asked here but none worked for me, usually returning an arror along the lines of not working for a boolean.*" Please show us what you tried, show us the exact error message you get and explain what about the error message you don't understand. Then we'll be able to help you. Otherwise, it's quite likely that someone will close this as a duplicate of one of the things you already tried, and that would be shame. – Heinzi Mar 29 '21 at 11:27
  • @Heinzi I've edited the question – Tim Verhees Mar 29 '21 at 11:36
  • "whilst I need it to be dynamic, not checking simply 1 property." - You always read the attributes for ONE property. If you need the attributes for all attributes, you have to get the list of properties and loop over them (`GetType().GetProperties()`). – Christoph Lütjen Mar 29 '21 at 12:53
  • Related: https://stackoverflow.com/questions/737151/how-to-get-the-list-of-properties-of-a-class – Christoph Lütjen Mar 29 '21 at 12:56

2 Answers2

1

you can use this

    var keys = typeof(T).GetProperties()
               .Where(e => e.GetCustomAttribute<PrimarykeyAttribute>(true) != null)

// can add this to Where Condition => e.GetCustomAttribute(true).Key == true

key parameter in PrimarykeyAttribute Can be remove, Properties that have this Attribute can be identified as key.

if you need some parameter in Attribute ,it is better to use this style.

[System.AttributeUsage(System.AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class PrimarykeyAttribute : Attribute
    {
        public PrimarykeyAttribute(short keyOrder)
            {
                this.KeyOrder  = keyOrder ;
            }

        public short KeyOrder { get; set; }
        
    }
Reza Basereh
  • 103
  • 6
0

If I'm understanding you correctly, you want to have a method that returns true if a specific property has the PrimaryKey attribute, and if that attribute has the value true, correct? Well, that's quite easy, we'll simply need to check whether a property has our attribute or not, and if so get the value of key. Here's your new PrimaryKey attribute:

public class PrimaryKeyAttribute : Attribute
{
    public bool IsKey { get; }

    public PrimaryKeyAttribute(bool isKey)
    {
        IsKey = isKey;
    }
}

And here's your new method to check whether a property has that attribute and IsKey is true:

public static class AttributeHelper
{
    public static bool HasPrimaryKeyTrue(this PropertyInfo self)
    {
        var attribute = self.GetCustomAttribtue<PrimaryKeyAttribute>(true);
        if (attribute == null)
            return false; // Attribute doesn't exist on this property

        return attribute.IsKey; // Return the value we set
    }
}

Although it would probably be easier to just remove the IsKey property and only apply the PrimaryKey attribute to properties which are, because [PrimaryKey(false)] is just the same as not having the primary key attribute on it at all


Usage: You can now use this in a wide variety of ways, but the one that seems like it would work best for you is to use it in a LINQ expression. Something like

var company = ...;
var companyPks = company.GetType().GetProperties().Where(x => x.HasPrimaryKeyTrue).ToList();

companyPksis now a list of property infos only where the respective property has thePrimaryKeyattribute, and whereIsKey` of it is set to true

MindSwipe
  • 7,193
  • 24
  • 47
  • This does answer my question yes, however the reason for [Primarykey(false)] being useful in this context is that if true it will be assumed as automatic and if false it will be assumed as non automatic, and to be added by SQL statements. Thanks for the help. – Tim Verhees Mar 30 '21 at 00:29