How to Set Attributes Values Using Reflection

how to change the attribute value using reflection

Field field = LoggerManager.class.getDeclaredField("_instance");
field.setAccessible(true);
field.set(null, new NewLoggerManager());
  • the first line obtains the Field definition for the _instance field. Using the "declared" method, because it is able to obtain private fields as well
  • setting the field to be accessible for reflective operations even if this would not be possible due to its visibility.
  • setting a new object. Passing null as target object, because the field is static

C# setting property values through reflection with attributes

There are a couple of separate issues here

  • typeof(MyClass).GetCustomAttributes(bool) (or GetType().GetCustomAttributes(bool)) returns the attributes on the class itself, not the attributes on members. You will have to invoke typeof(MyClass).GetProperties() to get a list of properties in the class, and then check each of them.

  • Once you got the property, I think you should use Attribute.GetCustomAttribute() instead of MemberInfo.GetGustomAttributes() since you exactly know what attribute you are looking for.

Here's a little code snippet to help you start:

PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach(PropertyInfo property in properties)
{
StoredDataValueAttribute attribute =
Attribute.GetCustomAttribute(property, typeof(StoredDataValueAttribute)) as StoredDataValueAttribute;

if (attribute != null) // This property has a StoredDataValueAttribute
{
property.SetValue(instanceOfMyClass, attribute.DataValue, null); // null means no indexes
}
}

EDIT: Don't forget that Type.GetProperties() only returns public properties by default. You will have to use Type.GetProperties(BindingFlags) to get other sorts of properties as well.

Get raw value of property attribute using Reflection

Since attribute constructor information are stored as metadata as well you can get the required information by calling the GetCustomAttributesData method. Have a look at this simple example:

class Program
{
[PasswordPropertyText]
public string Password1 { get; set; }

[PasswordPropertyText(true)]
public string Password2 { get; set; }

[PasswordPropertyText(false)]
public string Password3 { get; set; }

static void Main(string[] args)
{
var props = typeof(Program).GetProperties();
foreach(var prop in props)
{
var attributeData = prop.GetCustomAttributesData().First(x => x.AttributeType == typeof(PasswordPropertyTextAttribute));
Console.WriteLine($"{prop.Name}: {(attributeData.ConstructorArguments.Cast<CustomAttributeTypedArgument?>().FirstOrDefault()?.Value ?? true)}");
}
Console.ReadLine();
}
}

Output:

Password1: True
Password2: True
Password3: False

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

Java Reflection to set attributes

I think I may be overthinking this problem (i.e., I shouldn't be using reflection to set variables in this way)

Yep. Reflection is fairly slow and should only be used as a last resort. If this is simply to avoid having so much redundant code, consider using automatic code generation. For pure data objects, I would strongly recommend using protocol buffers; it will generate the getters / setters (you only need to declare the fields). Plus it allows for easy communication of the data between C++, Java, and Python.

If you have a class that has a lot of fields but isn't a pure data object... well

  1. You should consider whether all the fields should be mutable. (Do you really need setters?)
  2. Whether the fields should even be visible. (Do you need any accessors at all?)

It is often a good idea to make fields "final", initialize them in the constructor(s), and provide no access or provide limited access through an implemented interface.

Set object property using reflection

Yes, you can use Type.InvokeMember():

using System.Reflection;
MyObject obj = new MyObject();
obj.GetType().InvokeMember("Name",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, obj, "Value");

This will throw an exception if obj doesn't have a property called Name, or it can't be set.

Another approach is to get the metadata for the property, and then set it. This will allow you to check for the existence of the property, and verify that it can be set:

using System.Reflection;
MyObject obj = new MyObject();
PropertyInfo prop = obj.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance);
if(null != prop && prop.CanWrite)
{
prop.SetValue(obj, "Value", null);
}

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.



Related Topics



Leave a reply



Submit