|
|
|
Community Member
|
|
Just thinking... one very useful feature (that I can't see at the moment) would be the ability to add attributes at compile time. In particular, I'm thinking of generated classes (such as LINQ-to-SQL, LINQ-to-Entities, SOAP, WCF, etc); you can add a partial class with additional methods / class-attributes, but you can't add attributes to existing members. And if you edit the generated code it will get lost next time you rebuild etc.
So (for example) if the user defined a DisplayNameAspect that returns (perhaps) a CustomAttributeBuilder, i.e.
[DisplayNameAspect(Target="Bar", DisplayName="Hello world")] class Foo { public String Bar {get;set;} }
then this would be as though we had: class Foo { [DisplayName("Hello world")] public string Bar {get;set;} }
Again; the main driver here being partial classes where the member (Bar) is outside of our direct control; and obviously the caller would need to do something to provide the attribute in a convenient way (maybe CustomAttributeBuilder, maybe something else).
Thoughts? Is this already supported?
Marc
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
Good idea.
It is not supported, but would be pretty easy to realize (combined with CompoundAspect).
|
|
|
|
|
Community Member
|
|
|
Re the "something else", perhaps an easier option would be to clone the attributes from a prototype member (that might perhaps get removed in the process). Now to read up on compound aspect!
|
|
|
|
|
Colin Jack
Community Member
|
|
|
Good idea.
It is not supported, but would be pretty easy to realize (combined with CompoundAspect).
I was wondering how you would do this using the current version as it is a feature I would find very useful.
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
It is implemented as CustomAttributeInjectorAspect. You have to use a CompoundAspect add add CustomAttributeInjectorAspect whererever you want.
-g
|
|
|
|
|
Colin Jack
Community Member
|
|
|
Excellent thanks, do you happen to have any examples of using CustomAttributeInjectorAspect as its not immediate obvious to me what to do with it and googling didn't turn up anything much.
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
Here is an aspect that puts an Obsolete custom attributes on all methods:
[MulticastAttributeUsage(MulticastTargets.Class | MulticastTargets.Struct)] internal class MyAspect : CompoundAspect { internal const string ObsoleteMessage = "This method is now obsolete.";
private static readonly ConstructorInfo obsoleteConstructor = typeof(ObsoleteAttribute).GetConstructor(new[] { typeof(string) });
public override void ProvideAspects(object element, LaosReflectionAspectCollection collection) { Type targetType = (Type)element;
foreach (MethodInfo method in targetType.GetMethods()) { collection.AddAspect(method, new CustomAttributeInjectorAspect( new ObjectConstruction(obsoleteConstructor, ObsoleteMessage))); } } }
|
|
|
|
|
Colin Jack
Community Member
|
|
|
Ta, must admit I'm having little luck getting it working, was wondering how you recommend debugging these compound aspects?
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
|
<!-- m --><a class="postlink" href="http://doc.postsharp.org/1.5/UserGuide/Platform/Debugging.html">http://doc.postsharp.org/1.5/UserGuide/ ... gging.html</a><!-- m -->
|
|
|
|
|
Colin Jack
Community Member
|
|
Actually maybe I should check if what I am trying to do is even possible.
I want to use a Laos (CompoundAspect) attribute which will inject other Laos attributes onto members of the class. I was sure I'd done this in the past but no luck this time, will go look at the samples.
To be honest I'm probably making the mistake of coming back to P# after some time and get up to speed without re-reading the documents.
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
Aaah - this is something else. Look at the sample PostSharp.Samples.Binding.
Basically, using CompoundAspect, you can add any aspect to any declaration.
-g
|
|
|
|
|
Colin Jack
Community Member
|
|
Ahh ok ta, it was the use of "CustomAttributeInjectorAspect" that was messing it up, it works now thanks! <!-- s:) --> <!-- s:) -->
|
|
|
|
|
Colin Jack
Community Member
|
|
Hi,
Unfortunately the design is scuppering me. I need to copy attributes from one place to another and I don't want to have to write special code to copy particular types of attributes.
Unfortunately ObjectConstruction isn't much use for this because I don't want to have to specify what arguments to pass to the constructor of a new attribute, because I have no idea what constructor to use or what values to copy over. Instead I thus want to clone the attribute, and the way I was planning to do it looks like this:
object clone = cloneFactory.Clone(attributeToCopyOver);
var attributeAspect = new CustomAttributeInjectorAspect(clone);
collection.AddAspect(mappingDefinition.ToProperty, attributeAspect );
This doesn't work with your current design though (or maybe I need to look at other classes which I'll do next), but I definitely think it would be useful.
Ta,
Colin
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
|
Obviously, when you write an ObjectConstructor, you need to know what constructor has been known. There is no workaround. But you can know this info by requesting a CustomAttributeData. Then you could transform it under an ObjectConstruction. I agree it would be nice if the feature is included in PostSharp.
|
|
|
|
|
Colin Jack
Community Member
|
|
Hi,
I guess what I'm saying is in a future version it would be nice if instead of passing in an ObjectConstruction to CustomAttributeInjectorAspect I could either pass in the attribute to use or I could pass in an IObjectCreator interface with a single method called Create, allowing me to control the attribute creation.
Whether thats workable with PostSharp I don't know, I'll look at the CustomAttributeData idea and see if I can get it to do what I want.
Thanks again,
Colin
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
|
I guess what I'm saying is in a future version it would be nice if instead of passing in an ObjectConstruction to CustomAttributeInjectorAspect I could either pass in the attribute to use or I could pass in an IObjectCreator interface with a single method called Create
It will surely not be possible to pass a constructed attribute. We really need the information about how to create the attribute (constructor, arguments and named arguments), because this is the way how custom attributes are represented in a .NET assemblies. This is an intrinsic constraint of the MSIL specification and there is no workaround (the constraint makes perfectly sense, also).
-g
|
|
|
|
|
Colin Jack
Community Member
|
|
|
But you can know this info by requesting a CustomAttributeData. Then you could transform it under an ObjectConstruction. I agree it would be nice if the feature is included in PostSharp.
Wondering if you see this being added in the next version?
We'd find it very useful I think.
|
|
|
|
|
Gael Fraiteur
SharpCrafters
|
|
I forgot about this feature.
You can add a feature request in the issue tracker if you think it should be done.
-gael
|
|
|
|
|
Colin Jack
Community Member
|
|
My fault for not following up, its now reported:
<!-- m --><a class="postlink" href="http://www.postsharp.org/tracker/view.php?id=365">http://www.postsharp.org/tracker/view.php?id=365</a><!-- m -->
Thanks,
Colin
|
|