Usage of C# attribute methods - c#

In C#, what is the purpose of methods declared in attributes and how are they used?
As an example, have a look at the attribute MaxLengthAttribute: it has a bunch of methods. One of them is the IsValid() method, which is used to validate the property the attribute is applied to. How is this validation performed? I suppose the IsValid() method is called against the property, but I don't find documentation on how to call attribute methods.
Note: I have a Java background. In Java, annotations are intended as metadata and are declared as #intefaces, thus they don't have methods.

In almost all cases, the answer is simply: manually but by code that isn't yours. Some piece of code in some framework that you're using is intentionally checking for those attributes, and then if they exist: materializing them (preferably also with some kind of caching), and invoking the method.
Attributes don't do anything by themselves, but they are still types and can be materialized via the reflection APIs. If you want to write code to do this:
using System;
[SomeAttribute("boop")]
static class P
{
static void Main()
{
var obj = (SomeAttribute)Attribute.GetCustomAttribute(
typeof(P), typeof(SomeAttribute));
// note the attribute doesn't know the context
// so we need to pass that *in*; an attribute
// doesn't know what it has been attached to
obj?.DoSomething(typeof(P));
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Enum)]
class SomeAttribute : Attribute
{
public string Name { get; }
public SomeAttribute(string name)
=> Name = name;
public void DoSomething(Type type)
=> Console.WriteLine($"hey {type.Name} - {Name}");
}

Basically an attribute does nothing in itself, it has to be analysed by some kind of framework. What this framework actually does is completely up to the attributes creator. So the framework may just check if an attribute is present, however it can of course also call its members.
So imagine you have this code:
[MyAttribute]
class MyClass
{
}
class MyAttribute : Attribute
{
public void DoSomething();
}
Now you have some code that checks if the attribuite is present and if so calls DoSomething:
// get types with the attribute
var typesAndAttributes= myAssembly.GetTypes().Select(x => new
{
Type = x,
Attribute = Attribute.GetCustomAttribute(x, typeof(MyAttribute))
});
// now call DoSomething for every attribute
forerach(var e in typesAndAttributes)
{
e.Attribute?.DoSomething();
}
In your example of MaxLengthAttribute this means the following. If you´d decorate your member like this:
MaxLengthAttribute(2)
public int[] MyArr = new int[3];
and execute the code the framework calls IsValid for MyArr and will probably (not sure about it, didn´t inspect the sourcecode) return false, as the value contains 3 elements although only two are considered valid.

As an example, have a look at the attribute MaxLengthAttribute: it has a bunch of methods. One of them is the IsValid() method, which is used to validate the property the attribute is applied to. How is this validation performed? I suppose the IsValid() method is called against the property, but I don't find documentation on how to call attribute methods.
Here's a very simple example:
// Start off with an object we're going to validate
public class Foo
{
[MaxLength(5)]
public string Bar { get; set; }
}
var objectToValidate = new Foo() { Bar = "123456" };
// Use reflection to get a list of properties on the object
var properties = objectToValidate.GetType().GetProperties();
foreach (var property in properties)
{
// For each property, get the attributes defined on that property
// which derive from the ValidationAttribute base class
var attributes = property.GetCustomAttributes<ValidationAttribute>();
var propertyValue = property.GetValue(objectToValidate);
foreach (var attribute in attributes)
{
// For each attribute, call its IsValid method, passing in the value
// of the property
bool isValid = attribute.IsValid(propertyValue);
if (!isValid)
{
Console.WriteLine("{0} is invalid", property.Name);
}
}
}
This is more or less what Validator.ValidateObject does, except with a lot more caching.
(In the case of the DataAnnotations methods, the TypeDescriptor infrastructure is actually used. This lets you effectively add attributes to classes and their properties without modifying the source of the class directly).
Runnable example

Related

Why do CanRead and CanWrite return false in C# for properties with overridden accessors?

When trying to get properties accessors from derived properties or use CanRead / CanWrite, for some reason base auto-properties are not taken into account.
CanRead and CanWrite return values based only on the derived type, also GetMethod and SetMethod don't contain methods from base type.
However when writing code accessors from base type can be used (so that we can read overridden auto-property with only setter defined in derived type).
Here is the code to reproduce it written as an unit test:
using System.Reflection;
using NUnit.Framework;
[TestFixture]
public class PropertiesReflectionTests
{
public class WithAutoProperty
{
public virtual object Property { get; set; }
}
public class OverridesOnlySetter : WithAutoProperty
{
public override object Property
{
set => base.Property = value;
}
}
private static readonly PropertyInfo Property = typeof(OverridesOnlySetter).GetProperty(nameof(OverridesOnlySetter.Property));
// This one is passing
[Test]
public void Property_ShouldBeReadable()
{
var overridesOnlySetter = new OverridesOnlySetter {Property = "test"};
Assert.AreEqual(overridesOnlySetter.Property, "test");
}
// This one is failing
[Test]
public void CanRead_ShouldBeTrue()
{
Assert.True(Property.CanRead);
}
// And this is failing too
[Test]
public void GetMethod_ShouldBeNotNull()
{
Assert.NotNull(Property.GetMethod);
}
}
I expected last two tests to pass, what am I missing?
I expected last two tests to pass, what am I missing?
For a definitive answer, you'd have to ask the people who originally designed .NET and its type system. That said…
It seems to me that this is consistent with the goal of reflection providing information about how a type was written. Consider the alternative: what if the PropertyInfo object returned included both the setter from the derived class and the getter from the base class. It would be considerably more difficult to understand from the returned result what was actually declared where, and the PropertyInfo object itself would arguably be inconsistent. This is because there is the PropertyInfo.DeclaringType property which implies that all of the information for the member pertains just to that declaring type.
With members which are neither properties nor events (both of which encapsulate a pair of class members), you get the behavior you expected. Unless of course you pass BindingFlags.DeclaredOnly, which restricts the returned information to the declaring type. But in the case of those types of members, the DeclaringType property tells you unequivocally in which type the member was actually declared.
With a property, the DeclaringType tells you in which class the property was declared. And then the SetMethod and GetMethod properties tell you what that class declared.
IMHO, this makes the reflection API simpler, more consistent, and easier to understand. It does mean that you have to do a little more work to analyze virtual properties. But then, reflection is always going to involve "a little more work". :)
As Peter Duniho explains in his answer, this seems to require some work.
It would be easier if PropertyInfo had something like GetBaseDefinition(), but it does not (also this thread), so we have to go through the accessor method. It would also be easier if the method info for the accessor had a reference back to the property info, but it does not, so we run through all properties and assume there is exactly on match.
So here is a naive solution:
// does not necessarily work as expected if the property or one of its accessors
// (getter or setter) is not public
internal static bool CanReadExt(PropertyInfo pi)
{
if (pi.CanRead)
return true;
// assume we have a setter since we do not have a getter
var setter = pi.SetMethod
?? throw new Exception("Neither getter nor setter in property?");
// try to acquire setter of base property
var baseSetter = setter.GetBaseDefinition();
// if the property was not overridden, we can return
if (setter.DeclaringType == baseSetter.DeclaringType)
return false;
// try to find the base property
var basePi = baseSetter.DeclaringType.GetProperties()
.SingleOrDefault(x => x.SetMethod == baseSetter)
?? throw new Exception("Set accessor was overridden but we could not find property info for base property.");
// recursively call ourselves
return CanReadExt(basePi);
}
It returns true with your PropertiesReflectionTests.Property, so it works in that case. More care would be needed to handle every case, I guess.
This method can be made an extension method if you prefer.
A similar method CanWriteExt could be written.

How to introduce new property based on existing property and modify existing one?

I am trying to automate this XmlSerializer workaround pattern. See update below.
Is it possible to introduce new property based on existing property and modify attributes of existing one using PostSharp (or maybe some other AOP tool) ?
It would be preferable to make this modification at build time.
Sample source property:
public class TestType {
// Original version
[XmlAttribute()]
public DateTime ReqDateTime {
get { return this.reqDateTimeField; }
set { this.reqDateTimeField = value; }
}
}
Desired result (class declaration omitted):
// Modified version
// <original property> = "ReqDateTime"
// <original property> marked as XmlIgnore
// New property with name "<original property>ForXml" is introduced with code as per below
// XmlAttribute moved to the newly introduced <original property>ForXml property with parameter "<original property>"
[XmlIgnore()]
public DateTime ReqDateTime {
get { return this.reqDateTimeField;}
set { this.reqDateTimeField = value;}
}
[XmlAttribute("ReqDateTime")]
[EditorBrowsable(EditorBrowsableState.Never)]
public string ReqDateTimeForXml {
get { return Common.GetAndFormatDate(this, Common.GetCaller()); }
set { Common.ParseAndSetDate(this, value, Common.GetCaller()); }
}
I have found PostSharp tutorial on introducing members, but no information on (a) how to introduce members with dynamic names and (b) how to move attributes ([XmlAttribute] in my case) from existing member to the newly created one.
I do not need an exact solution - just some hints would be enough.
Update: From further research I can conclude that PostSharp does not support dynamic method naming. Also PostSharpIt cannot remove attribute from existing method.
So let me reword the problem in yet another approach to solve it:
1) Inject 10 new properties named IntroducedProperty0, IntroducedProperty1, ... This seems to be trivial. Properties are hardcoded.
2) Somehow after/with (1) add attribute [XmlAttribute("nameOftheOriginalProperty#N")] to the first M of the IntroducedPropertyN where N=0..9 and M<=N. This is kind of dynamic. This is possible when adding attributes to existing (not injected) members. However they say you cannot add attributes to injected members.
Rest of the injected methods (from M to N) should be marked as [XmlIgnore].
3) Mark original methods of class with [XmlIgnore].
Maybe this is achievable with Fody?

Passing Attributes of a Auto-Implemented Property to its field

I have the following Problem: I would like to add an attribute to an auto-implemented property prop of a class Foo in the first step.
In a second step I'm iterating over all fields of Foo and I copy values to these fields (values of fields of auto-implemented Properties are also found and copied). In this part I need access to the information of the Attribute.
class FieldSetter
{
// This Method is called from outside and should work for any class
private void SetFieldValues(object unknownObject)
{
foreach (var field in
unknownObject.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.Static).Where((field) => !field.IsLiteral))
{
if (!EvalAttribute(Attribute.GetCustomAttributes(field))) // the Attribute should be accessed here
{
// Do something if no special Information is set
field.SetValue(a, "default Value");
}
else
{
// Do special things
field.SetValue(a, "special Value");
}
}
}
internal static bool EvalAttribute(Attribute[] attributes)
{
foreach (System.Attribute attr in attributes)
{
var myAttr = attr as MyAttribute;
if (myAttr != null)
{
if (myAttr.SomeAttributeValues == "Specific Attribute Value")
{
return true;
}
}
}
return false;
}
}
// This class is a example for how a given Object can look like
class Foo
{
[MyAttribute("Example Information")] // This Attribute won't be accessed via prop-Field
int prop { get; set; }
[MyAttribute("Another Example Information")] // This Attribute won't be accessed via prop-Field
int field;
//... lots of other fields and properties
}
[System.AttributeUsage(System.AttributeTargets.All)]
class MyAttribute : Attribute
{
public MyAttribute(string someInformation)
{
SomeAttributeValues = someInformation;
}
public string SomeAttributeValues;
}
You can't do this. If you need to have the attribute on the field, you need to declare the field yourself and not use auto-properties. Alternately, you can reflect over the properties which will have the attribute when you look for them.
If you can guarantee that the properties you're interested in will always be auto-implemented, and you have some idea of what compiler will be used to compile the types you're interested in, you could leverage the fact that the backing fields for auto-generated properties follow a specific naming convention. For example, the code you've provided ends up with a field name like this:
<prop>k__BackingField
This is a distinctive name, which cannot be produced directly by C# code, so if you run into a field with a name like this you could parse out the property name from between the angle brackets, and use GetProperty() on that name.
However, this is a hacky solution because:
The name used for backing fields is an implementation detail, which could theoretically change in future versions of .NET, or for alternative compilers like Mono.
There's nothing to ensure that the fields you find will always be tied to auto-properties. What would your expectations be if you ran into this?
class Foo
{
int field;
[MyAttribute("Example Information")]
int prop { get{return field;} set {return field;} }
//... lots of other fields and properties
}
I'd strongly suggest that you spend more time analyzing what your real business need and constraints are, and see if there's not another, more robust way to approach this problem.

Can you create a custom attribute in c# with "hidden" properties?

Normally when you create a custom Attribute class, any public property with a getter and a setter is automatically exposed to the person applying the attribute on the class, so that the person using the attribute can specify the value of that property.
I want a custom attribute class which exposes a getter and setter for a particular property, but which does not allow this property to be specified as a named argument to the attribute on creation. Example:
[AttributeUsage(AttributeTargets.Class)]
class MyCustomAttribute : Attribute
{
public bool MyProperty
{
get { /* do something */ }
set { /* do something */ }
}
}
// The following line should be a compiler error, MyProperty should
// be hidden for attribute initialization!
[MyCustomAttribute(MyProperty=true)]
class MyClass
{
};
Is there any way to achieve this?
You could simply make the property (or just the property setter) internal, if you intend to use it elsewhere in your code, but don't want others to see it.
Alternatively, if you want to expose the property other users, but just disallow setting it in the declarative syntax, you could not expose a property setter, but provide a different method to set the value if you need to:
class MyCustomAttribute : Attribute
{
public bool MyProperty
{
get { /* do something */ }
}
public void SetMyProperty(bool value)
{
/* do something */
}
}
If the property is public, there is no way of preventing it from being assigned when the attribute is applied. As suggested by dtb in the comments, you could use getter and setter methods instead, but that probably wouldn't help you...
Attributes are not made to be modified at runtime. When you retrieve the attributes from a class or member (or anything else) using reflection, you only get copies of these attributes, so even if you modified them, the next time you would retrieve them, you would get a fresh, unmodified copy.

Add dynamic property to .NET classes

Is it possible to add my own custom property to any type of object?
In this example the object is List but I mean for any kind of object (.NET or custom ones).
For example extend List<string> to add an extra property called MyProperty:
List<string> myList = new List<string>();
myList.MyProperty = "some value";
then call a method ProcessList(List<string> list):
ProcessList(myList);
public void ProcessList(List<string> list)
{
// get the custom property value
string myprop = list.MyProperty.ToString();
....................
do other work
}
No. There is no "extension property" implementation in .NET. Extension methods are more of a compiler trick, and only work as static methods because they do not require their own state (at least should not).
A property would require a backing field, which would require other functionality in order to implement properly.
Note that certain frameworks do support this. For example, if your object derives from DependencyObject, you could use Attached Properties to implement this functionality.
Not the way you're describing. Extension methods are probably the closest you'll get.
public static class QueryExtensions
{
public static bool HasMapping(this Demand role)
{
return role.DemandMappings.Count > 0;
}
}
You would use the above example like this:
var role = GetDemand(Request.QueryString["id"]);
if (role != null)
{
var mapped = role.HasMapping();
}

Categories

Resources