Let's have a attribute with an int paramter in the ctor
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class EntityBindingAttribute : Attribute
{
public int I { get; set; }
public EntityBindingAttribute(int i)
{
I = i;
}
}
How can I access this value using code ?
You would use the Attribute.GetCustomAttributes Method, with the overload that matches the object where the attribute has been set.
For example if the attribute is set on a method, something like:
MethodInfo mInfo = myClass.GetMethod("MyMethod");
foreach(Attribute attr in Attribute.GetCustomAttributes(mInfo))
{
if (attr.GetType() == typeof(EntityBindingAttribute))
{
int i = ((EntityBindingAttribute)attr).I);
}
}
// Get all the attributes for the class
Attribute[] _attributes = Attribute.GetCustomAttributes(typeof(NameOfYourClass));
// Get a value from the first attribute of the given type assuming there is one
int _i = _attributes.Where(_a => _a is EntityBindingAttribute).First().I;
Related
This question already has answers here:
Find a private field with Reflection?
(11 answers)
Closed 1 year ago.
I want to get all fields that have null values but i aint even getting any fields:
[Serializable()]
public class BaseClass
{
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
FixNullString(this);
}
public void FixNullString(object type)
{
try
{
var properties = type.GetType().GetFields();
foreach (var property in from property in properties
let oldValue = property.GetValue(type)
where oldValue == null
select property)
{
property.SetValue(type, GetDefaultValue(property));
}
}
catch (Exception)
{
}
}
public object GetDefaultValue(System.Reflection.FieldInfo value)
{
try
{
if (value.FieldType == typeof(string))
return "";
if (value.FieldType == typeof(bool))
return false;
if (value.FieldType == typeof(int))
return 0;
if (value.FieldType == typeof(decimal))
return 0;
if (value.FieldType == typeof(DateTime))
return new DateTime();
}
catch (Exception)
{
}
return null;
}
}
And then i have a class :
[Serializable()]
public class Settings : BaseClass
{
public bool Value1 { get; set; }
public bool Value2 { get; set; }
}
But when i comes to
var properties = type.GetType().GetFields();
then i get 0 fields, it should find 2 fields.
Is type.getType().GetFields() wrong to use ? or am i sending in the wrong class to the base class?
Type.GetFields methods returns all public fields. Fields that the compiler autogenerates for you are private, so you need to specify correct BindingFlags.
type.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
The fields generated by the compiler corresponding to properties of your class have the CompilerGenerated attribute. Also the compiler will generate get and set methods for handling these fields, depending on the declaration of your property.
From CompilerGeneratedAttribute MSDN documentation:
Distinguishes a compiler-generated element from a user-generated element. This class cannot be inherited.
The name of these fields have the format <PropertyName>k_BackingField,the methods set and get names have the format set_PropertyName and get_PropertyName where PropertyName is the name of property.
For example, your Settings class is compiled as follows:
[Serializable]
public class Settings : BaseClass
{
public Settings(){}
// Properties
[CompilerGenerated]
private bool <Value1>k__BackingField;
[CompilerGenerated]
private bool <Value2>k__BackingField;
[CompilerGenerated]
public void set_Value1(bool value)
{
this.<Value1>k__BackingField = value;
}
[CompilerGenerated]
public bool get_Value1()
{
return this.<Value1>k__BackingField;
}
[CompilerGenerated]
public void set_Value2(bool value)
{
this.<Value2>k__BackingField = value;
}
[CompilerGenerated]
public bool get_Value2()
{
return this.<Value2>k__BackingField;
}
}
If you wish exclude this backing fields you can use this method:
public IEnumerable<FieldInfo> GetFields(Type type)
{
return type
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null);
}
Value1 and Value2 in your Settings class are properties rather than fields, so you'll need to use GetProperties() to access them.
(Using the { get; set; } syntax tells the compiler that you want a property, but that it should generate the get and set for you, along with a hidden private field that contains the data.)
How to get value and type of "strx" at runtime? Cant get value of cell (properties) at runtime when using generics (as result of under code is "null").
Example
public class Foo
{
public int x, y;
public string strx, stry;
}
public void GetCellValueByName<T>(GridView gridview, string name/)
{
T = (T)Activator.CreateInstance(typeof(T));
object row = gridview.GetRow(gridview.GetSelectedRows()[0]);
if (row != null && row is T)
{
columnType = (T)gridview.GetRow(gridview.GetSelectedRows()[0]);
PropertyInfo info = columnType.GetType().GetProperty(name);
if (info != null)
{ // Here I got always null
info.GetValue(columnType, null);
}
}
}
string valueOfStrx = GetCellValueByName<Foo>(grid, "strx");
The problem is that in class Foo, strx is a field (member variable):
public string strx, stry;
In your method, you try to use GetProperty, but this will not find the field:
PropertyInfo info = columnType.GetType().GetProperty(name);
So either change the member to a property
public string strx { get; set; }
public string stry { get; set; }
or use GetField instead:
FieldInfo info = columnType.GetType().GetField(name);
// ...
info.GetValue(columnType); // Note that GetValue for a field does not take a second parameter
I need to be able to read the value of my attribute from within my Method, how can I do that?
[MyAttribute("Hello World")]
public void MyMethod()
{
// Need to read the MyAttribute attribute and get its value
}
You need to call the GetCustomAttributes function on a MethodBase object.
The simplest way to get the MethodBase object is to call MethodBase.GetCurrentMethod. (Note that you should add [MethodImpl(MethodImplOptions.NoInlining)])
For example:
MethodBase method = MethodBase.GetCurrentMethod();
MyAttribute attr = (MyAttribute)method.GetCustomAttributes(typeof(MyAttribute), true)[0] ;
string value = attr.Value; //Assumes that MyAttribute has a property called Value
You can also get the MethodBase manually, like this: (This will be faster)
MethodBase method = typeof(MyClass).GetMethod("MyMethod");
[MyAttribute("Hello World")]
public int MyMethod()
{
var myAttribute = GetType().GetMethod("MyMethod").GetCustomAttributes(true).OfType<MyAttribute>().FirstOrDefault();
}
The available answers are mostly outdated.
This is the current best practice:
class MyClass
{
[MyAttribute("Hello World")]
public void MyMethod()
{
var method = typeof(MyClass).GetRuntimeMethod(nameof(MyClass.MyMethod), Array.Empty<Type>());
var attribute = method.GetCustomAttribute<MyAttribute>();
}
}
This requires no casting and is pretty safe to use.
You can also use .GetCustomAttributes<T> to get all attributes of one type.
If you store the default attribute value into a property (Name in my example) on construction, then you can use a static Attribute helper method:
using System;
using System.Linq;
public class Helper
{
public static TValue GetMethodAttributeValue<TAttribute, TValue>(Action action, Func<TAttribute, TValue> valueSelector) where TAttribute : Attribute
{
var methodInfo = action.Method;
var attr = methodInfo.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
return attr != null ? valueSelector(attr) : default(TValue);
}
}
Usage:
var name = Helper.GetMethodAttributeValue<MyAttribute, string>(MyMethod, x => x.Name);
My solution is based on that the default value is set upon the attribute construction, like this:
internal class MyAttribute : Attribute
{
public string Name { get; set; }
public MyAttribute(string name)
{
Name = name;
}
}
In case you are implementing the setup like #Mikael Engver mentioned above, and allow multiple usage. Here is what you can do to get the list of all the attribute values.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCase : Attribute
{
public TestCase(string value)
{
Id = value;
}
public string Id { get; }
}
public static IEnumerable<string> AutomatedTests()
{
var assembly = typeof(Reports).GetTypeInfo().Assembly;
var methodInfos = assembly.GetTypes().SelectMany(m => m.GetMethods())
.Where(x => x.GetCustomAttributes(typeof(TestCase), false).Length > 0);
foreach (var methodInfo in methodInfos)
{
var ids = methodInfo.GetCustomAttributes<TestCase>().Select(x => x.Id);
yield return $"{string.Join(", ", ids)} - {methodInfo.Name}"; // handle cases when one test is mapped to multiple test cases.
}
}
I used this method :
public static TAttributeMember? GetMethodAttributeValue<TAttribute, TAttributeMember>(Expression<Func<object>> property, Func<TAttribute, TAttributeMember> valueSelector) where TAttribute : Attribute
{
var methodInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
var attr = methodInfo?.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
return attr != null && valueSelector != null ? valueSelector(attr) : default(TAttributeMember);
}
Then can use like this:
var group = GetMethodAttributeValue<FieldAttribs, FieldGroups>(() => dd.Param2, a => a.Group);
Is it possible in an C# attribute to explicitly check what named parameters are set?
The problem is that I have a couple of parameters of type bool in an attribute, and I want to explicitly check which one of them are set. I know I could probably make them nullable and check against that in the code, but is there a better way?
This appears to do what you want, assuming you control the attribute itself:
using System;
[AttributeUsage(AttributeTargets.All)]
class SampleAttribute : Attribute
{
private bool hasFlag = false;
public bool HasFlag { get { return hasFlag; } }
private bool flag = false;
public bool Flag
{
get { return flag; }
set
{
flag = value;
hasFlag = true;
}
}
}
class Test
{
static void Main()
{
foreach (var method in typeof(Test).GetMethods())
{
var attributes = (SampleAttribute[])
method.GetCustomAttributes(typeof(SampleAttribute), false);
if (attributes.Length > 0)
{
Console.WriteLine("{0}: Flag={1} HasFlag={2}",
method.Name,
attributes[0].Flag,
attributes[0].HasFlag);
}
}
}
[Sample(Flag = true)]
public static void WithFlagTrue() {}
[Sample(Flag = false)]
public static void WithFlagFalse() {}
[Sample]
public static void WithoutFlag() {}
}
Results:
WithFlagTrue: Flag=True HasFlag=True
WithFlagFalse: Flag=False HasFlag=True
WithoutFlag: Flag=False HasFlag=False
I'm not sure whether it's really a good idea, mind you...
If this attribute is defined by you, you could provide a method to return all parameters which are set.
If not, i think your question equals to how to check what properties are set in an object.
Bool value either true or false, and the default value for bool variables is false, so you cant know whether the value of a bool var is set or not without define them as nullable then check nullity, or you can create a flag for each boolean property you have!
Why you need that anyway? isnt this check enough for you
if(myBoolProp)
{
//My boolean var is checked, lets do something
}
else
{
//My boolean var not checked :( cant do anything
}
Please try:
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
private Nullable<int> _PropertyI;
private Nullable<bool> _PropertyB;
private String _Name;
public int PropertyI
{
get
{
return _PropertyI.HasValue ? _PropertyI.Value : default(int);
}
set
{
this._PropertyI = value;
}
}
public bool PropertyB
{
get
{
return _PropertyB.HasValue ? _PropertyB.Value : default(bool);
}
set
{
this._PropertyB = value;
}
}
public String Name
{
get
{
return this._Name;
}
set
{
this._Name = value;
}
}
public String[] GetAvailableParameters()
{
IList<String> names = new List<String>();
Type type = this.GetType();
FieldInfo[] fields
= type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
Type fieldType = field.FieldType;
Object fieldValue = field.GetValue(this);
if (fieldValue != null)
{
names.Add(field.Name.Substring(1));
}
}
return names.ToArray();
}
}
Given a custom attribute, I want to get the name of its target:
public class Example
{
[Woop] ////// basically I want to get "Size" datamember name from the attribute
public float Size;
}
public class Tester
{
public static void Main()
{
Type type = typeof(Example);
object[] attributes = type.GetCustomAttributes(typeof(WoopAttribute), false);
foreach (var attribute in attributes)
{
// I have the attribute, but what is the name of it's target? (Example.Size)
attribute.GetTargetName(); //??
}
}
}
Hope it's clear!
do it the other way around:
iterate
MemberInfo[] members = type.GetMembers();
and request
Object[] myAttributes = members[i].GetCustomAttributes(true);
or
foreach(MemberInfo member in type.GetMembers()) {
Object[] myAttributes = member.GetCustomAttributes(typeof(WoopAttribute),true);
if(myAttributes.Length > 0)
{
MemberInfo woopmember = member; //<--- gotcha
}
}
but much nicer with Linq:
var members = from member in type.GetMembers()
from attribute in member.GetCustomAttributes(typeof(WoopAttribute),true)
select member;