Add attributes inside custom attribute in c# - c#

I want to dynamically add attributes to properties of a given class, because the project will get bigger and the procedure is totally repeatinglly, something like so :
public class MyAttr : Attribute {
public MyAttr () {
foreach(var prop in properties) {
prop.Attributes.Add([Display(Name = nameof(prop.Name), ResourceType = typeof(Labels))]);
}
}
}
And use it on classes :
[MyAttr]
public class SomeClass {
public string Name {get; set;}
public string Description {get; set;}
}
of course the code above is not a real program, but I tried to make it simple.
Is it possible to do this? or if not, is there a workaround?
Update: I know there's an attribute called CallerMemberName that retrieves name of a given property, but how to get the property itself and add more attributes to it?

I think you might be able to make something work combining the below answers from other posts.
Access object properties from Attribute: Can C# Attributes access the Target Class?
Add attributes at runtime: How to add an attribute to a property at runtime by creating new types at run-time.
Unless you're going to be making regular changes across all the properties it may just be better to deal with the repetitive work up front. There are inevitably risks/issues down the road when doing stuff across the board like this.

Related

C#, Outline Interface-Attributes on implementing classes during design time

Interfaces are no types, so when implementing them, their property attributes are not inherited. (which would be true of a base-class)
So, I'm currently wrapping my head around how to make this happen. Following example should pretty much explain what I mean, but unfortunately is not working as expected.
Reason is obvisously to centralize Instructions / Attributes without having to copy / paste them over and over.
public interface IPermissionBasedControl
{
[Browsable(true), Category("PermissionSystem"), Description("AccessKey required in order to use this control.")]
String PermissionKey { get; set; }
}
public class ExtendedTextBox : TextBox, IReadOnlyControl, IDataBindable, IPermissionBasedControl
{
...
[AttributeProvider(typeof(IPermissionBasedControl))]
public string PermissionKey { get; set; }
...
}
Expectation: Visual Studio Designer will pick the Category, Browsable and Description Attribute from IPermissionBasedControl and display the property PermissionKey accordingly in the Designers Property-Window, when working with a ExtendedTextBox.
Actual result: Nothing happens, Default Category Misc is applied, no Description, Browsable default yes is applied.
Is it not working, because Visual Studio Designer does not respect the AttributProvider-Attribute?
Is it not working, because AttributeProvider cannot target an Interface?
I've also tried method access to no success:
public class ExtendedTextBox : TextBox, IReadOnlyControl, IDataBindable, IPermissionBasedControl
{
...
[AttributeProvider(nameof(IPermissionBasedControl), nameof(IPermissionBasedControl.PermissionKey))]
public string PermissionKey { get; set; }
...
}
Okay, It seems like I had a wrong interpretation about what AttributeProvider is doing:
AttributeProviders description is Enables Attribute Redirection - but this doesn't mean, that it will (in my example) attach the Attributes of IPermissionBasedControl.PermissionKey to ExtendedTextBox.PermissionKey, the AttributeProvider is having effect on the Attributes of the type of the property.
i.e.: If I would specify
[AttributeProvider(typeof(Color))]
public object PermissionKey { get; set; }
the VisualStudio Designer would now Apply the Attributes of Color to the Value-Field for picking the object. (And therefore show a color-picker)
So, technically spoken, the AttributeProvider redirects Attributes for the type of the property, not for the property itself.

C#: How to add a class member named "protected"

I'm fairly new to C# but have extensive experience in Objective-C and OOP. I'm using Json.NET to automatically parse API responses to objects. It so happens that one of the objects returned has a property named protected. Obviously this is a problem, because protected is a keyword for class member declaration.
"protected": true
Is it possible to add a member with the name protected at all?
Is it possible to add setters and getters that get triggered, if the parser tries to set the protected property? (but assign the value to a private member named _protected)
Should I modify the parser to behave different when he encounters a property named protected?
Thanks for any advice.
1:
For question #1: You can put an # symbol before it any keyword you want to use as a variable name.
E.g.
public string #protected {get; set; }
I recommend against doing this, however. You should be able to remap the "protected" field in your JSON to a different property in your POCO.
2:
private string _protected;
public string #protected
{
get
{
//any additional code you want
return _protected;
}
set
{
//any additional code you want
_protected = value;
}
}
3:
Up to you!
I implemented this solution:
[JsonProperty("protected")] public bool Protected { get; set; }
Like Daniel Mann suggested in his comment:

Create Attribute to represent multiple sub attributes in C#

I have the following type of code sample across one of my projects...
[Obfuscation(Exclude = true)]
[UsedImplicitly]
public DelegateCommand<object> OpenXCommand { get; private set; }
I am finding the attributes are adding a lot of "noise" to the code - I also see it in a way violating the DRY principle since I may have several properties like this in one class, all with the same attribute decoration.
Q: Is there some way I can set up an attribute that will represent a combination of sub attributes?
Ideally I would like something that looks like this..
[MyStandardCommandAttribute]
public DelegateCommand<object> OpenXCommand { get; private set; }
I have not implemented my own attributes before so I am unsure if this is possible. Any suggestions?
No. Your one attribute cannot "be" Obfuscation and UsedImplicitly at the same time (there's no multiple inheritance in C#).
Code looking for e.g. UsedImplicitlyAttribute has no way of knowing that MyStandardCommandAttribute is supposed to represent UsedImplicitlyAttribute (unless you control all of the code using all of these attributes).
Unfortunately, there's no way to do this in C#.
But, if you control the places that read these attributes (with reflection), you can do it by convention.
For example, you can have a marker interface that will "annotate" your attribute with the attributes it proxies (sounds like a meta-attribute):
public interface AttributeProxy<T>
where T : Attribute {}
public class MyStandardCommandAttribute :
Attribute,
AttributeProxy<ObfuscationAttribute>,
AttributeProxy<UsedImplicitlyAttribute> {}
(Of course, you also have to match the right AttributeUsages. And you can't set properties on the proxied attributes like this.)
Now, you could go a step further and use an IL manipulation library, like Mono.Cecil, to actually transfer the attributes appropriately in a post-compilation step. In this case, it would work even if it weren't you reflecting on these attributes.
Update: still in the reflect-your-own-attributes scenario, you can use the below code to get to proxied attributes, even setting properties values:
public interface IAttributeProxy {
Attribute[] GetProxiedAttributes();
}
public class MyStandardCommandAttribute : Attribute, IAttributeProxy {
public Attribute[] GetProxiedAttributes() {
return new Attribute[] {
new ObfuscationAttribute { Exclude = true },
new UsedImplicitlyAttribute()
};
}
}
Use this extension method on your reflection code:
public static object[] GetCustomAttributesWithProxied(this MemberInfo self, bool inherit) {
var attributes = self.GetCustomAttributes(inherit);
return attributes.SelectMany(ExpandProxies).ToArray();
}
private static object[] ExpandProxies(object attribute) {
if (attribute is IAttributeProxy) {
return ((IAttributeProxy)attribute).GetProxiedAttributes().
SelectMany(ExpandProxies).ToArray(); // don't create an endless loop with proxies!
}
else {
return new object[] { attribute };
}
}

Remove C# attribute of a property dynamically

I have a class with a set of properties As given below.
class ContactInfo
{
[ReadOnly(true)]
[Category("Contact Info")]
public string Mobile { get; set; }
[Category("Contact Info")]
public string Name{ get; set; }
}
The objects of this class is being assigned to a property grid, so that the users can update an existing contact. you can see that Mobile is marked as ReadOnly.
But, when I want to add an entirely new Contact, I would want the users to be able to edit the contact Mobile also. For that I need to remove the Readonly property dynamically from the Type, before assigning the object to the property grid. Is it possible?
You can not remove the attribute at runtime, but you can use reflection to change the ReadOnly attribute's ReadOnly private backing field to False. Making it the equivalent of [ReadOnly(false)]
See this article for details:
http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html
Edit: fixed link
I have to agree w/ Omu; you're really talking about two classes (view models) in this case, to support your two different views. Something like
CreateContactViewModel and EditContactViewModel
it's not possible at the moment to remove attributes dinamycally (at runtime)
as a suggestion you can do 2 classes: one with the attributes and one without
The CodingLight.com blog moved to blogspot (the above link is broken).
See http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html.
Moreover, SysAdmin's followup did not mention the [RefreshProperties(RefreshProperties.All)] attribute that seems to be necessary for an actually-working solution.
Finally, I believe that even David Morton (author of the quoted article) missed one very important thing: if the class (ContactInfo, in SysAdmin's followup example) does not have at least one property with the [ReadOnly] attribute defined at compile time, then when the "isReadOnly" FieldInfo is set to true at runtime the result is that the whole class turns read-only.
I followed up the suggestion by Legenden. Here is what I came up with
class ContactInfo
{
[ReadOnly(true)]
[Category("Contact Info")]
public string Mobile { get; set; }
[Category("Contact Info")]
public string Name{ get; set; }
public void SetMobileEdit(bool allowEdit)
{
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["Mobile"];
ReadOnlyAttribute attrib = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];
FieldInfo isReadOnly = attrib.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
isReadOnly.SetValue(attrib, !allowEdit);
}
}

How to make a Attribute aware of the Name of the Proprty it is on?

I want to implement a simple attribute that is used to map Database Columns to Properties.
So what i have so far is something that attached like so:
[DataField("ID")]
public int ID { get; set; }
[DataField("Name")]
public String Name { get; set; }
[DataField("BirD8")]
public DateTime BirthDay { get; set; }
Is there a way that I can make the attribute "aware" of the field it is on, so that for the properties where the name is the same as the ColumnName I can just apply the attribute without the name parameter, or would I have to deal with that at the point where I reflect the properties. I want to end up doing just this:
[DataField]
public int ID { get; set; }
[DataField]
public String Name { get; set; }
[DataField("BirD8")]
public DateTime BirthDay { get; set; }
The attribute itself won't be aware of what it's applied to, but the code processing the attributes is likely to be running through PropertyInfo values etc and finding the attributes associated with them. That code can then use both the property and the attribute appropriately.
To make things simpler, you might want to write a method on the attribute to allow it to merge its information with the information from the property, so you'd call:
DataFieldAttribute dfa = propertyInfo.GetCustomAttributes(...); // As normal
dfa = dfa.MergeWith(propertyInfo);
Note that for the sake of sanity this should create a new instance of the attribute, rather than changing the existing one. Alternatively, you might want a whole separate class to represent "the information about a data field":
DataFieldAttribute dfa = propertyInfo.GetCustomAttributes(...); // As normal
DataFieldInfo info = dfa.MergeWith(propertyInfo);
That way you could also construct DataFieldInfo objects without any reference to attributes, which might be a nice conceptual separation - allowing you to easily load the config from an XML file or something similar if you wanted to.
If you don't mind using postsharp you can look Here, at a previous question I have asked which was close. I ended up using the compile time validate to do what I wanted, although there are other options, like CompileTimeInitalize.
public override void CompileTimeInitialize(object element)
{
PropertyInfo info = element as PropertyInfo;
//....
}

Categories