I need to read the attribute of a property using reflection
For example I get the following :
[XmlElement("Id")]
[CategoryAttribute("Main"), ReadOnly(true),
Description("This property is auto-generated")]
[RulesCriteria("ID")]
public override string Id
{
get { return _ID; }
set
{
_ID = value;
}
}
i want to get the " read only "value of this property using reflection
can anybody help
It's difficult to write the code for your case without knowing the Type name. Hope below example helps.
using System;
using System.Reflection;
public class Myproperty
{
private string caption = "Default caption";
public string Caption
{
get{return caption;}
set {if(caption!=value) {caption = value;}
}
}
}
class Mypropertyinfo
{
public static int Main(string[] args)
{
Console.WriteLine("\nReflection.PropertyInfo");
// Define a property.
Myproperty Myproperty = new Myproperty();
Console.Write("\nMyproperty.Caption = " + Myproperty.Caption);
// Get the type and PropertyInfo.
Type MyType = Type.GetType("Myproperty");
PropertyInfo Mypropertyinfo = MyType.GetProperty("Caption");
// Get and display the attributes property.
PropertyAttributes Myattributes = Mypropertyinfo.Attributes;
Console.Write("\nPropertyAttributes - " + Myattributes.ToString());
return 0;
}
}
MSDN
public static bool PropertyReadOnlyAttributeValue(PropertyInfo property)
{
ReadonlyAttribute attrib = Attribute.GetCustomAttribute(property, typeof(ReadOnlyAttribute));
return attrib != null && attrib.IsReadOnly;
}
public static bool PropertyReadOnlyAttributeValue(Type type, string propertyName)
{
return PropertyReadOnlyAttributeValue(type.GetProperty(propertyName));
}
public static bool PropertyReadOnlyAttributeValue(object instance, string propertyName)
{
if (instance != null)
{
Type type = instance.GetType();
return PropertyReadOnlyAttributeValue(type, propertyName);
}
return false;
}
Related
This question already has answers here:
Get property value from string using reflection
(24 answers)
Closed 4 years ago.
What I'm trying to do is setting the value of the property in a class using a string. For example, my class has the following properties:
myClass.Name
myClass.Address
myClass.PhoneNumber
myClass.FaxNumber
All the fields are of string type so I know ahead of time that it's always a string. Now, I want to be able to set the properties using a string as you could do with a DataSet object. Something like this:
myClass["Name"] = "John"
myClass["Address"] = "1112 River St., Boulder, CO"
Ideally, I want to just assign a variable and then set the property using that string name from the variable:
string propName = "Name"
myClass[propName] = "John"
I was reading about reflection and maybe it's the way to do it but I'm not sure how to go about setting that up while keeping the property access intact in the class. I want to still be able to use:
myClass.Name = "John"
Any code examples would be really great.
You can add indexer property, a pseudocode:
public class MyClass
{
public object this[string propertyName]
{
get
{
// probably faster without reflection:
// like: return Properties.Settings.Default.PropertyValues[propertyName]
// instead of the following
Type myType = typeof(MyClass);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
return myPropInfo.GetValue(this, null);
}
set
{
Type myType = typeof(MyClass);
PropertyInfo myPropInfo = myType.GetProperty(propertyName);
myPropInfo.SetValue(this, value, null);
}
}
}
You can add an indexer to your class and use reflection to aces the properties:
using System.Reflection;
public class MyClass {
public object this[string name]
{
get
{
var properties = typeof(MyClass)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
if (property.Name == name && property.CanRead)
return property.GetValue(this, null);
}
throw new ArgumentException("Can't find property");
}
set {
return;
}
}
}
May be something like this?
public class PropertyExample
{
private readonly Dictionary<string, string> _properties;
public string FirstName
{
get { return _properties["FirstName"]; }
set { _properties["FirstName"] = value; }
}
public string LastName
{
get { return _properties["LastName"]; }
set { _properties["LastName"] = value; }
}
public string this[string propertyName]
{
get { return _properties[propertyName]; }
set { _properties[propertyName] = value; }
}
public PropertyExample()
{
_properties = new Dictionary<string, string>();
}
}
is there a way to get the value of a property of a object based on its name?
For example if I have:
public class Car : Vehicle
{
public string Make { get; set; }
}
and
var car = new Car { Make="Ford" };
I want to write a method where I can pass in the property name and it would return the property value. ie:
public string GetPropertyValue(string propertyName)
{
return the value of the property;
}
return car.GetType().GetProperty(propertyName).GetValue(car, null);
You'd have to use reflection
public object GetPropertyValue(object car, string propertyName)
{
return car.GetType().GetProperties()
.Single(pi => pi.Name == propertyName)
.GetValue(car, null);
}
If you want to be really fancy, you could make it an extension method:
public static object GetPropertyValue(this object car, string propertyName)
{
return car.GetType().GetProperties()
.Single(pi => pi.Name == propertyName)
.GetValue(car, null);
}
And then:
string makeValue = (string)car.GetPropertyValue("Make");
You want Reflection
Type t = typeof(Car);
PropertyInfo prop = t.GetProperty("Make");
if(null != prop)
return prop.GetValue(this, null);
Expanding on Adam Rackis's answer - we can make the extension method generic simply like this:
public static TResult GetPropertyValue<TResult>(this object t, string propertyName)
{
object val = t.GetType().GetProperties().Single(pi => pi.Name == propertyName).GetValue(t, null);
return (TResult)val;
}
You can throw some error handling around that too if you like.
In addition other guys answer, its Easy to get property value of any object by use Extension method like:
public static class Helper
{
public static object GetPropertyValue(this object T, string PropName)
{
return T.GetType().GetProperty(PropName) == null ? null : T.GetType().GetProperty(PropName).GetValue(T, null);
}
}
Usage is:
Car foo = new Car();
var balbal = foo.GetPropertyValue("Make");
Simple sample (without write reflection hard code in the client)
class Customer
{
public string CustomerName { get; set; }
public string Address { get; set; }
// approach here
public string GetPropertyValue(string propertyName)
{
try
{
return this.GetType().GetProperty(propertyName).GetValue(this, null) as string;
}
catch { return null; }
}
}
//use sample
static void Main(string[] args)
{
var customer = new Customer { CustomerName = "Harvey Triana", Address = "Something..." };
Console.WriteLine(customer.GetPropertyValue("CustomerName"));
}
To avoid reflection you could set up a Dictionary with your propery names as keys and functions in the dictionary value part that return the corresponding values from the properties that you request.
2 Very short options, 1 with a default value if it fails:
public object GetPropertyValue_WithDefault(
object _t,
string _prop,
object _default = null
)
{
PropertyInfo pi = _t.GetType().GetProperty(_prop);
return (pi == null
? _default
: pi.GetValue(_t, null)
);
}
public object GetPropertyValue(object _t, string _prop)
{
//because of "?." will return null if property not found
return _t.GetType().GetProperty(_prop)?.GetValue(_t, null);
}
How can I use reflection to get the name and declaring class of a property of a generic type. The purpose is to get an exception if I read a property where nothing has been written so far. One of the problems is that the check must be independent of the declaring class.
value.GetType().DeclaringType is always null.
using System;
namespace TestCodeContract
{
public struct CheckForNull<T> where T : struct
{
private T? backingField;
public static implicit operator T(CheckForNull<T> value)
{
if (!(value.backingField.HasValue))
{
var t1 = value.GetType().DeclaringType; // always null.
var propertyName = "Delta"; // TODO get from Reflection
var className = "ContractClass"; // TODO get from Reflection
var msg = String.Format("Proprety '{0}' in class '{1}' is not initialized", propertyName, className);
throw new ApplicationException(msg);
}
return value.backingField.Value;
}
public static implicit operator CheckForNull<T>(T value)
{
return new CheckForNull<T> { backingField = value };
}
}
public class ContractClass
{
public CheckForNull<int> Delta { get; set; }
public void Test1()
{
int x = Delta; // Wanted: "Property 'Delta' in class 'ContractClass' is not initialized"
}
}
}
No, you can't do it like that. I would suggest something like this instead:
// You could do this without the constraint, with a bit of extra work.
public class ReadOnlyAfterWrite<T> where T : struct
{
private T? value;
private readonly string property;
private readonly string type;
public ReadOnlyAfterWrite(string property, string type)
{
this.property = property;
this.type = type;
}
public T Value
{
get
{
if (value == null)
{
// Use type and property here
throw new InvalidOperationException(...);
}
return (T) value;
}
set { this.value = value; }
}
}
public class ContractClass
{
// This is what I'd do in C# 6. Before that, probably just use string literals.
private readonly ReadOnlyAfterWrite<int> delta =
new ReadOnlyAfterWrite(nameof(Delta), nameof(ContractClass));
public int Delta
{
get { return delta.Value; }
set { delta.Value = value; }
}
}
While it's not terribly clean in implementation, I think it's a better public API - the fact that it's guarded is invisible to the caller, who just sees an int property.
I need a list which can have its items queried for a particular property, and then returns the item if that property has the correct value. I came up with the following:
public class MyList<T>
{
public T[] items;
public Get( string name )
{
foreach( T item in items )
{
if( item.name == name )
return item;
}
return null; // if not found
}
}
The above gives a compile error because type T doesn't necessarily have the property that i'm checking. That makes sense, but what do I have to do to get this behaviour. Please note that I cannot use a Dictionary for reasons outside the scope of this question, although it is true that a Dictionary is essential what i'm trying to re-create.
Put a constraint behind your function definition
public class MyList<T> where T : YourObjectThatHasNameProperty
You could use Reflection like this:
public static Object TryGetPropertyValue(Object fromThis, String propertyName, Boolean isStatic)
{
// Get Type
Type baseType = fromThis.GetType();
// Get additional binding flags
BindingFlags addFlag = BindingFlags.Instance;
if(isStatic)
addFlag = BindingFlags.Static;
// Get PropertyInfo
PropertyInfo info = baseType.GetProperty(propertyName, BindingFlags.Public | addFlag);
// Check if we found the Property and if we can read it
if(info == null || !info.CanRead)
return null;
// Return the value
return info.GetValue(fromThis, null);
}
Edit: If the function return null, you can assume that the property does not exist on the provided Object.
You could use reflection to see if T has that property:
Type type = item.GetType();
bool hasproperty = type.GetProperties().Where(p => p.Name.Equals("name")).Any();
You need to constrain T to be of a type that has such a property:
interface INamed {
string Name { get; }
}
public class MyList<T> where T : INamed
public T[] items;
public T Get( string name ) {
foreach( T item in items ) {
if( item.Name == name )
return item;
}
return null; // if not found
}
}
Then, for instance,
class Foo : INamed {
private readonly string name;
private readonly int foo;
public string Name { get { return this.name; } }
public Foo(string name, int foo) {
this.name = name;
this.foo = foo;
}
}
MyList<Foo> list = // some instance of MyList<Foo>
Foo alice = list.Get("Alice");
Use a generic constraint.
public interface IHasName
{
string name;
}
public class MyList<T> where T : IHasName
{
public T[] items;
public Get( string name )
{
foreach( T item in items )
{
if( item.name == name )
return item;
}
return null; // if not found
}
}
public class CustomProperty<T>
{
private T _value;
public CustomProperty(T val)
{
_value = val;
}
public T Value
{
get { return this._value; }
set { this._value = value; }
}
}
public class CustomPropertyAccess
{
public CustomProperty<string> Name = new CustomProperty<string>("cfgf");
public CustomProperty<int> Age = new CustomProperty<int>(0);
public CustomPropertyAccess() { }
}
//I jest beginer in reflection.
//How can access GetValue of CPA.Age.Value using fuly reflection
private void button1_Click(object sender, EventArgs e)
{
CustomPropertyAccess CPA = new CustomPropertyAccess();
CPA.Name.Value = "lino";
CPA.Age.Value = 25;
//I did like this . this is the error “ Non-static method requires a target.”
MessageBox.Show(CPA.GetType().GetField("Name").FieldType.GetProperty("Value").GetValue(null ,null).ToString());
}
How about a method like this:
public Object GetPropValue(String name, Object obj) {
foreach (String part in name.Split('.')) {
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
And use it like so:
Object val = GetPropValue("Age.Value", CPA);
Read the error message.
Non-static methods and properties are associated with an instance of a class - and so you need to provide an instance when trying to access them through reflection.
In the GetProperty.GetValue method, you need to specify the object for which you want to get the property value. In your case, it would be: GetValue(CPA ,null)