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

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.

Related

Usage of C# attribute methods

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

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?

Attributes vs. CustomAttributes in PropertyInfo

I've been working with Reflections and wanted to get all the attributes declared for a property. There are two properties under PropertInfo class which are CustomAttributes and Attributes.
According to the MSDN, they are explained as follows:
Attributes:
This property represents the attributes associated with a member. All
members have a set of attributes that are defined in relation to the
specific type of member. The property attributes let the user know if
this property is the default property, a SpecialName property, and so
on.
Note: The code sample given in the PropertyInfo.Attributes page doesn't even work.
Custom Attributes:
An array that contains all the custom attributes applied to this
member, or an array with zero elements if no attributes are defined.
However, when I run this code for them, Attributes returns nothing while CustomAttributes returns Required.
void Main()
{
var attributes = typeof(Myproperty).GetProperty("Caption").CustomAttributes;
//var attributes = typeof(Myproperty).GetProperty("Caption").Attributes;
attributes.Dump(); //Dump is a LinqPad method which dumps everything to the outpu window
}
public class Myproperty
{
private string caption = "Default caption";
[Required]
public string Caption
{
get{return caption;}
set {if(caption!=value) {caption = value;}
}
}
}
PropertyInfo.Attributes doesn't have anything to do with the Attribute class. Check the PropertyAttributes enumeration for values you may encounter. These are CLR implementation details that have no obvious connection to C# code. Yes, that was an unfortunate naming choice.
To find attributes like your [Required] attribute you must use the CustomAttributes property.

What is the meaning of "get"? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In C# what does this code with “get” mean?
I'm using open source project. In this project there is function.
public virtual ICollection<Customer> AffiliatedCustomers
{
get
{
return _affiliatedCustomers ?? (_affiliatedCustomers = new List<Customer>());
}
protected set { _affiliatedCustomers = value; }
}
I don't understand what is the meaning of "get".
Can you please explain this function.
AffiliatedCustomers is a property.
The get defines the property getter, which is a method used internally to return the value by the property. It allows you to use this given an instance of the class like so:
var customers = theClass.AffiliatedCustomers; // Looks like a field, but is a property
Properties can also have a set section, as well, as this one does (protected set { _affiliatedCustomers = value; }), which gives you control over what happens when you set the value via the Property.
For details, see Properties in C#.
This is not a function. It is a property. A property is basically a fancy wrapper for some variable. For example, declaring the following property:
public string SomeProperty { get; set; }
will actually compile to something like this:
private string backing_SomeProperty;
public void set_SomeProperty(string value)
{
backing_SomeProperty = value;
}
public int get_SomeProperty()
{
return backing_SomeProperty;
}
That's an example of an automatic property. Of course, you can also define the getter and setter methods yourself like this:
public string SomeProperty
{
get
{
// some logic code here
// then return some value
}
set
{
// some logic code here
// then set some value
}
}
This is a property,
Quoted by msdn:
Properties are members that provide a flexible mechanism to read, write, or compute the values of private fields. Properties can be used as though they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily while still providing the safety and flexibility of methods.
Please refer to this link for more:
http://msdn.microsoft.com/en-us/library/x9fsa0sw(v=vs.80).aspx
Properties have a getter and a setter - their purpose is obvious (to get and set the value of the property).
When you use auto properties, there is still a get and a set, but the backing variable is automatically implemented for you. In the example you have given the author of the code has chosen to have their own implementation of the get - in this case to automatically initialise the member variable the first time the property is accessed.

Acessing the backing field in an auto property

Is there any way to access the backing field for a property in order to do validation, change tracking etc.?
Is something like the following possible? If not is there any plans to have it in .NET 4 / C# 4?
public string Name
{
get;
set
{
if (value != <Keyword>)
{
RaiseEvent();
}
<Keyword> = value;
}
}
The main issue I have is that using auto properties doesn't allow for the same flexibility in validation etc. that a property with a explicit backing field does. However an explicit backing field has the disadvantage in some situations of allowing the class it is contained in to access the backing field when it should be accessing and reusing the validation, change tracking etc. of the property just like any other class that may be accessing the property externally.
In the example above access to the backing field would be scoped to the property thus preventing circumvention of the property validation, change tracking etc.
Edit: I've changed < Backing Field > to < Keyword >. I would propose a new keyword similar to value. field would do nicely although I'm sure it's being used in a lot of existing code.
No there isn't. If you want to access the backing field, then don't use auto properties and roll your own.
I agree that it would be great to have a field that was only accessible by the property and not by the rest of the class. I would use that all the time.
As the MSDN states:
"In C# 3.0 and later, auto-implemented
properties make property-declaration
more concise when no additional logic
is required in the property accessors.
They also enable client code to create
objects When you declare a property as
shown in the following example, the
compiler creates a private, anonymous
backing field can only be accessed
through the property's get and set
accessors."
Since you have additional logic in you accessors, the use of auto-implemented properties is not appropriate in your scenario.
While the backing field does exist, it is given a mangled name to stop you referencing it easily - the idea is that you never reference the field directly. For interests sake, you can use Reflector to disassemble your code and discover the field name, but I would recommend you not use the field directly as this name may indeed be volatile, so your code could break at any time.
Having read your comments in Mehrdad's answer, I think I understand your problem a bit better.
It appears that you are concerned about the ability of the developer to access private state in the class they are writing, bypassing your validation logic, etc. This suggests that the state should not be contained in the class at all.
I would suggest the following strategy. Write a generic class that represents a ValidatedValue. This class holds only the backing value and only allows access/mutation via get and set methods. A delegate is passed to the ValidatedValue to represent the validation logic:
public class ValidatedValue< T >
{
private T m_val;
public ValidationFn m_validationFn;
public delegate bool ValidationFn( T fn );
public ValidatedValue( ValidationFn validationFn )
{
m_validationFn = validationFn;
}
public T get()
{
return m_val;
}
public void set(T v)
{
if (m_validationFn(v))
{
m_val = v;
}
}
}
You could, of course, add more delegates as required (eg, to support pre/post change notification).
Your class would now use the ValidatedValue in place of a backing store for your property.
The example below shows a class, MyClass, with an integer that is validated to be less than 100. Note that the logic to throw an exception is in MyClass, not the ValidatedValue. This allows you to do complex validation rules that depend on other state contained in MyClass. Lambda notation was used to construct the validation delegate - you could have bound to a member function instead.
public partial class MyClass
{
private ValidatedValue<int> m_foo;
public MyClass()
{
m_foo = new ValidatedValue<int>(
v =>
{
if (v >= 100) RaiseError();
return true;
}
);
}
private void RaiseError()
{
// Put your logic here....
throw new NotImplementedException();
}
public int Foo
{
get { return m_foo.get(); }
set { m_foo.set(value); }
}
}
Hope that helps - somewhat off the original topic, but I think it's more inline with your actual concerns. What we have done is taken the validation logic away from the property and put it on the data, which is exactly where you wanted it.
No, but you can in a subclass:
public class Base
{
public string Name
{
get;
virtual set;
}
}
public class Subclass : Base
{
// FIXME Unsure as to the exact syntax.
public string Name
{
override set
{
if (value != base.Name)
{
RaiseEvent();
}
base.Name = value;
}
}
}
If you're gonna do so, why you are using auto properties?!
A simple property has done it way back in 1.0. I don't think it makes sense to add complexity to the language for every special case. You either need the property to do plain store/retrieve model or need more than that. In the latter case, a normal property will do.
You can't do this I'm afraid. That's one of the reasons I started writing MoXAML Power Toys, to provide the ability to convert automatic properties into Notify properties.

Categories

Resources