Custom Attribute on Property - Getting Type and Value of Attributed Property

Custom attribute on property - Getting type and value of attributed property

Something like the following,, this will use only the first property it comes accross that has the attribute, of course you could place it on more than one..

    public object GetIDForPassedInObject(T obj)
{
var prop = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.FirstOrDefault(p => p.GetCustomAttributes(typeof(IdentifierAttribute), false).Count() ==1);
object ret = prop !=null ? prop.GetValue(obj, null) : null;

return ret;
}

Get custom attribute from specific object property/field

After another day of trial and error I decided to make use of Selman22 answer with a little modification. This is code I created:

public class TestObject : iTestObject 
{
// Declare fields
[FieldAttr("prop_testfld1")]
public FLDtype1 testfld1 = new FLDtype1();

[FieldAttr("prop_testfld2")]
public FLDtype2 testfld2 = new FLDtype2();

[FieldAttr("prop_testfld3")]
public FLDtype1 testfld3;
}

public class FLDtype1 : iField
{
public string Value { get; set; }
}

public class FLDtype2 : iField
{
public Guid Value { get; set; }
}

public sealed class FieldAttr: System.Attribute
{
private string _txt;

public FieldAttr(string txt)
{
this._txt = txt;
}

public string Text { get { return this._txt; } }
}

public interface iField { }
public interface iTestObject { }

public static class Extensions
{
public static FieldAttr GetFieldAttr<T>(this T source, Expression<Func<iField>> field) where T : iTestObject
{
// Get member body. If no body present, return null
MemberExpression member = (MemberExpression)field.Body;
if (member == null) { return null; }

// Get field info. If no field info present, return null
FieldInfo fieldType = typeof(T).GetField(member.Member.Name);
if (fieldType == null) { return null; }

// Return custom attribute
return fieldType.GetCustomAttribute<FieldAttr>();
}
}

Usage:

public class Program
{
public static void Main()
{
TestObject test = new TestObject();
Console.WriteLine(test.GetFieldAttr(() => test.testfld1).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld2).Text);
Console.WriteLine(test.GetFieldAttr(() => test.testfld3).Text);
}
}

Uses:

using System;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;

I have implemented interfaces to protect the GetFieldAttr method

@Sulman22: Thnx for the response!

Reflection - get attribute name and value on property

Use typeof(Book).GetProperties() to get an array of PropertyInfo instances. Then use GetCustomAttributes() on each PropertyInfo to see if any of them have the Author Attribute type. If they do, you can get the name of the property from the property info and the attribute values from the attribute.

Something along these lines to scan a type for properties that have a specific attribute type and to return data in a dictionary (note that this can be made more dynamic by passing types into the routine):

public static Dictionary<string, string> GetAuthors()
{
Dictionary<string, string> _dict = new Dictionary<string, string>();

PropertyInfo[] props = typeof(Book).GetProperties();
foreach (PropertyInfo prop in props)
{
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
AuthorAttribute authAttr = attr as AuthorAttribute;
if (authAttr != null)
{
string propName = prop.Name;
string auth = authAttr.Name;

_dict.Add(propName, auth);
}
}
}

return _dict;
}

C# get property value from object using custom attribute

In your example, you're getting the customattributes of the class instead of the properties.

Here is an example:

private object GetValueBySectionFlag(object obj, string flagName)
{
// get the type:
var objType = obj.GetType();

// iterate the properties
var prop = (from property in objType.GetProperties()
// iterate it's attributes
from attrib in property.GetCustomAttributes(typeof(SectionFlagAttribute), false).Cast<SectionFlagAttribute>()
// filter on the name
where attrib.Name == flagName
// select the propertyInfo
select property).FirstOrDefault();

// use the propertyinfo to get the instance->property value
return prop?.GetValue(obj);
}

Note: this will return only the first property which contains the SectionFlagAttribute with the right name. You could modify the method to return multiple values. (like a collection of propertyname/value)


Usage:

// a test instance.
var obj = new ApplicationStatusFlags { IceAttributeStatement = true };

// get the value by SectionFlag name
var iceAttributeStatement = GetValueBySectionFlag(obj, "APPLICANTSTATEMENT");

If the returned value is null then the flag is not found or the property's value is null.

Get value from custom attribute-decorated property?

Your need to pass object itself to GetValue, not a property object:

var value = prop.GetValue(o, null);

And one more thing - you should use not .First(), but .FirstOrDefault(), because your code will throw an exception, if some property does not contains any attributes:

object attr = (from row in propattr 
where row.GetType() == typeof(MyAttribute)
select row)
.FirstOrDefault();

Get property name by attribute and its value

Use GetCustomAttributes to find the attributes, and LINQ to filter and get an anonymous object which holds the Property and the Attribute.

Use PropertyInfo.GetValue to read the actual value.

But please beware that the reflection calls are pretty expensive:

var propertiesWithAttribute = typeof(Entity).GetProperties()
// use projection to get properties with their attributes -
.Select(pi => new { Property = pi, Attribute = pi.GetCustomAttributes(typeof(MyAttribute), true).FirstOrDefault() as MyAttribute})
// filter only properties with attributes
.Where(x => x.Attribute != null)
.ToList();

foreach (Entity entity in collection)
{
foreach (var pa in propertiesWithAttribute)
{
object value = pa.Property.GetValue(entity, null);
Console.WriteLine($"PropertyName: {pa.Property.Name}, PropertyValue: {value}, AttributeName: {pa.Attribute.GetType().Name}");
}
}

Read value of custom attributes

It seems your only issue is retrieving PropertyInfos those annotated by [Custom(Export = true)]. You can achieve that this way:

var exportedProps = type_info.GetProperties()
.Where(p => p.PropertyType.GetCustomAttribute<CustomAttribute>()?.Export == true)

How do I get the member to which my custom attribute was applied?

Since there seems to be a lot of confusion with respect to how the stack frames and methods work, here is a simple demonstration:

static void Main(string[] args)
{
MyClass c = new MyClass();
c.Name = "MyTest";
Console.ReadLine();
}

class MyClass
{
private string name;

void TestMethod()
{
StackTrace st = new StackTrace();
StackFrame currentFrame = st.GetFrame(1);
MethodBase method = currentFrame.GetMethod();
Console.WriteLine(method.Name);
}

public string Name
{
get { return name; }
set
{
TestMethod();
name = value;
}
}
}

The output of this program will be:

set_Name

Properties in C# are a form of syntactic sugar. They compile down to getter and setter methods in the IL, and it's possible that some .NET languages might not even recognize them as properties - property resolution is done entirely by convention, there aren't really any rules in the IL spec.

Now, let's say for the moment that you had a really good reason for a program to want to examine its own stack (and there are precious few practical reasons to do so). Why in the world would you want it to behave differently for properties and methods?

The whole rationale behind attributes is that they are a kind of metadata. If you want a different behaviour, code it into the attribute. If an attribute can mean two different things depending on whether it's applied to a method or property - then you should have two attributes. Set the target on the first to AttributeTargets.Method and the second to AttributeTargets.Property. Simple.

But once again, walking your own stack to pick up some attributes from the calling method is dangerous at best. In a way, you are freezing your program's design, making it far more difficult for anybody to extend or refactor. This is not the way attributes are normally used. A more appropriate example, would be something like a validation attribute:

public class Customer
{
[Required]
public string Name { get; set; }
}

Then your validator code, which knows nothing about the actual entity being passed in, can do this:

public void Validate(object o)
{
Type t = o.GetType();
foreach (var prop in
t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (Attribute.IsDefined(prop, typeof(RequiredAttribute)))
{
object value = prop.GetValue(o, null);
if (value == null)
throw new RequiredFieldException(prop.Name);
}
}
}

In other words, you're examining the attributes of an instance that was given to you but which you don't necessarily know anything about the type of. XML attributes, Data Contract attributes, even Attribute attributes - almost all attributes in the .NET Framework are used this way, to implement some functionality that is dynamic with respect to the type of an instance but not with respect to the state of the program or what happens to be on the stack. It is very unlikely that you are actually in control of this at the point where you create the stack trace.

So I'm going to recommend again that you don't use the stack-walking approach unless you have an extremely good reason to do so which you haven't told us about yet. Otherwise you are likely to find yourself in a world of hurt.

If you absolutely must (don't say we didn't warn you), then use two attributes, one that can apply to methods and one that can apply to properties. I think you'll find that to be much easier to work with than a single super-attribute.



Related Topics



Leave a reply



Submit