Programmatically add an attribute to a method or parameter - c#

I can use TypeDescriptor.AddAttributes to add an attribute to a type in runtime. How do I do the same for a method and parameter? (maybe 2 separate questions...)

TypeDescriptor.AddAttributes only affects a very specific use-case; i.e. from within System.ComponentModel. For the rest of reflection, it knows nothing about the extra attribute. And indeed, System.ComponentModel doesn't really apply to methods or parameters.
So in short; you can't. You will need to store this information somewhere else (bespoke), or add it at compile-time.

As I see from analyzing the TypeDescriptor class in Reflector, the .AddAttributes method internally calls the .AddProvider method. The TypeDescriptionProvider instance passed to it is actually responsible for providing meta-data. You could try adding the [TypeDescriptionProviderAttribute] attribute to your class and implement your own provider by deriving from the TypeDescriptionProvider class. As the documentation says, by overriding TypeDescriptionProvider.CreateInstance, you could provide a substitute object whose type has all necessary attributes. I suspect that the attributes applied to methods inside the substitution type will also take effect. However, I haven't tried that myself, so feel free to experiment...

Related

In FluentAssertions, why is Should a method instead of a property?

In FluentAssertions, you can make various claims in various formats.
x.Should().BeEquivalentTo(y);
x.ShouldBeEquivalentTo(y);
are both valid assertions.
Why is Should a method and not a property? I haven't seen any examples in which Should takes a parameter, so it seems to me like it could have easily been a property.
You can also assert that
x.Should().NotBeNull().And.BeEquivalentTo(y);
Here, And is a property instead of a method. Shouldn't And and Should each be the same type of element (methods/properties)?
TL;DR
Was there a valid reason behind the design choice to make Should a method in FluentAssertions instead of a property?
Should() is an extension method being added onto the class of x. You can only add extension methods -- C# doesn't have extension properties.
And is a property on whatever class NotBeNull() returns. There we have control over the class, and can add real properties to it.
Should() is a method because of the limitations of the C# language. It's an extension method; a method that is defined in the FluentAssertions library to be available to call on any type (hence x.Should()) - even though the original code for the class doesn't implement the method.
You can't implement extension properties, so Should has to be a method.
That method returns an object defined within FluentAssertions, as does NotBeNull(), and so these objects can include properties where it's relevant/useful/meaningful to do so.
In short: the valid reason is that it's the only choice available.

Extension method - having to use this keyword?

I have added an extension method to the ASP.NET System.Web.UI.Page.
Every page in my application inherits from this class.
I cannot just access the extension method, however. I must type this.MyMethod(); instead of just being able to use MyMethod(). I thought that methods/attributes of this were inherently in the default scope. What am I not understanding? Or is this a nuance of extension methods?
I thought that methods/attributes of
this were inherently in the default
scope.
They are. But extension methods are not methods of this in the default scope; they are static methods accessible via syntactic sugar provided as a courtesy by the compiler.
I believe you already know this, but just to clarify: if ExtensionMethod is an extension method of the class whose scope you're currently in, typing this:
this.ExtensionMethod();
...is the same as:
SomeStaticClass.ExtensionMethod(this);
this needs to be passed as a parameter to ExtensionMethod. The first way above, the compiler simply does this for you.
Naturally, they could have implemented things differently so that the compiler "brings in" extension methods as well as class members into the default scope; they just simply chose not to. Personally, I like that; but I guess it's a subjective matter. Anyway, if you dislike having to type this, it's only a small annoyance, right?
is this a nuance of extension methods?
Yes, it is. (As others have explained.)
If you want to use the method without any qualification, then you could just make a class that inherits from Page and includes your method (minus the first paramater, of course). Then make each page in your application inherit from your new custom page.
In order to use extension method you should declare:
using Namespace.Where.Extension.Method.Is.Located
And don't forget that class that holds extension method should be static.

C# AttributeUsage for Specific Class

Is it possible to have something like AttributeUsage to restrict the use of an attribute to a specific class (not just AttributeTargets.Class - that would be any class)?
One way to accomplish this, if you have access to the specific class, is detailed by Marc Gravel here: http://marcgravell.blogspot.com/2009/06/restricting-attribute-usage.html. Basically you implement the attribute as a protected class of the specific type. Then it can only be used by that type.
No. There is nothing in the framework that would do this.
However, the code that uses the attribute in question could always check to make sure that the class's type is the specific class (or one of its subclasses).
Attributes, by themselves, do nothing - so this should have the same effect.
Make all data in the Attribute accessible only by a public static method which takes the class you want in question and checks to see if it has the given attribute.

How to reflect the generic parameter that was used for inheritance

Let's say I have the following class hierarchy: TaskViewer inherits from ListViewer<Task> which in turn inherits from ViewerBase.
If I debug into a method that is declared in ViewerBase and look at this.GetType(), it correctly returns TaskViewer. However, I cannot find a property or method which will return me the generic parameter that was used in the inheritance, i.e. Task. Obviously if I was in the context of TaskViewer or ListViewer<T> then I would easily know this.
I can see that it was Task by looking at the BaseType.FullName property, but I've been through the list and nothing I can see identifies itself as having used that generic argument.
How might I get the original generic parameter from within this method in the root class?
You can access the generic argument of the base type as follows (assuming only a single type argument).
typeof(TaskViewer).BaseType.GetGenericArguments()[0]
In ViewerBase you would use
this.GetType().BaseType.GetGenericArguments()[0]
but it seems quite weired to look at the generic type arguments of a derived class in the base class. You cannot know waht the actual type is, hence not if it has generic arguments at all. Could you tell something about your usage scenario?
Make sure you're doing this for a good reason. If you're doing this to put the type returned in an if-statement and do something different depending on the type, this is a use for polymorphism, and possibly a generic constraint, not reflection.

Web services - XmlInclude in a derived class instead of a base class?

I am using an abstract class as a parameter in a web service call. Currently, I am including an XmlInclude of a derived class in the base class, like so:
[XmlInclude(typeof(DerivedClass))]
public abstract class BaseClass
{
}
However, I'd rather not include all of the derived types in the base class.
In http://www.pluralsight.com/community/blogs/craig/archive/2004/07/08/1580.aspx, the author mentions an alternative - writing the attribute above the web method instead, like so:
[WebMethod]
[System.Xml.Serialization.XmlInclude(typeof(DerivedClass))]
public BaseClass getClass() {
return new DerivedClass();
}
However, I'd also like to not put the derived types in the web service either. Is there a way of keeping the attribute in the derived type?
Lets take it as a given that the framework would somehow need to know what types are in the type hiearchy when deserialization occurs, and how those types are represented in xml. It really has no way to infer this information if it is stored in a derived type.
You then have a couple of options:
- use the XmlInclude attribute
- specify the set of allowed types in the XmlSerializer Constructor overload
Now, if you're expecting a subclass to be passed in to the webservice, the webserver controls serialization and deserialization. So the XmlSerializer contstructor is no longer an option.
As you say, you can put the attribute on the webservice method instead of directly on the class. There's a trade-off between keeping your class "pure" and remembering to put those attributes in every place they may be required.
Of course, the real problem appears to be that you are trying to use your business objects as the message format in your webservice layer.
If you really want to keep the "message format" and "business object" responsibilities separate, then have another class (with the full hierarchy) for which the only use is to be used as a webservice parameter. In that case, there's no problem with sticking all the XmlInclude attributes you need, on the base class. Then, when making calls to the webservice, adapt your business object to and from the message format object. This gives you the added benefit of not applying webservice type constraints to the types of your parameters (eg no interfaces as parameters).
Of course, this method isn't as convenient.
In the end, the webservice needs to know what types to expect, or it won't be able to serialize and deserialize them properly.
And yes, this is a long winded explanation of why the answer is no, you can't only keep the attribute in the derived type. I'd love to be wrong though :)
I don't see how in this case. If you are deserializing there is an overload for specify extra types array where you pass in the derived types.

Categories