Tuesday, September 18, 2007

Copying custom attributes with CustomAttributeData

The story of Spring.NET solution for copying of custom attributes from the original class to the proxy continues with a new member of a .NET2.0 family - System.Reflection.CustomAttributeData http://msdn2.microsoft.com/en-us/library/system.reflection.customattributedata.aspx

Mark Pollack re-pointed me into this direction a day ago. Truly I tried to execute CustomAttributeData.GetCustomAttributes from the debugger line before trying the Mono.Cecil approach few weeks ago, but it threw exception to me and I happily progressed to Mono.Cecil without caring about it.

Mark is absolutely right though that solution by means of only .NET framework would be the best one.
Lets take another look onto the class and how it can be useful in our case.

Applying the code from the msdn sample to the test class:

[CustomTest(100, -100, ReadWriteProperty = "Test of a read write property")]
[ServiceBehavior(
    Name = "WcfServiceWithServiceBehavior",
    ConfigurationName = "WcfService",
    Namespace = "http://spring.net/wcf.tests/2006")]
[WebService(
    Namespace="http://springframework.net/webservices/" ,
    Name = "WcfAndWebService"
    )]
public class WcfAndWebService : WebService, IWcfService
{

  Brings the following result: 

[System.Web.Services.WebServiceAttribute(Namespace = "http://springframework.net/webservices/", Name = "WcfAndWebService")]
   Constructor: Void .ctor()
   Constructor arguments:
   Named arguments:
      MemberInfo: System.String Namespace
      Type: System.String Value:
http://springframework.net/webservices/
      MemberInfo: System.String Name
      Type: System.String Value: WcfAndWebService
[System.ServiceModel.ServiceBehaviorAttribute(Name = "WcfServiceWithServiceBehavior", Namespace = "
http://spring.net/wcf.tests/2006", ConfigurationName = "WcfService")]
   Constructor: Void .ctor()
   Constructor arguments:
   Named arguments:
      MemberInfo: System.String Name
      Type: System.String Value: WcfServiceWithServiceBehavior
      MemberInfo: System.String Namespace
      Type: System.String Value:
http://spring.net/wcf.tests/2006
      MemberInfo: System.String ConfigurationName
      Type: System.String Value: WcfService
[Dsi.Mono.Cecil.TestTypes.A.CustomTestAttribute((Int32)100, (Int32)-100, ReadWriteProperty = "Test of a read write property")]
   Constructor: Void .ctor(Int32, Int32)
   Constructor arguments:
      Type: System.Int32 Value: 100
      Type: System.Int32 Value: -100
   Named arguments:
      MemberInfo: System.String ReadWriteProperty
      Type: System.String Value: Test of a read write property

Test class is not picked up randomly. The fact that test runs proves that issue of CustomAttributeData with WebService attribute http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=161522 really seems to be fixed (though still a mystery, how it has been applied? Would not a guy with a clean .NET 2.0 redistributable face this problem?)
I created a post on msdn forum thread dedicated to this issue http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=542365&SiteID=1. Lets see if there is going to be a response.

UPDATE!: Just after an hour, there is a response and Peter Ritchie says:
"Yes, there was a security update that was released recently that had some various other fixes. If you've downloaded and installed .NET 3.5 Beta 2, or Visual Studio 2008 Beta 2; you've also installed .NET 2.0 Service Pack 1 beta."
This explains why I had an exception 6 weeks ago but not now!
It also means that if your system is running on clean .NET 2.0 install you will still have this exception unless you install .NET 2.0 Service Pack 1 beta (on your production system?!)


Here is the list of all other issues logged for this class on the vs feedback site:
https://connect.microsoft.com/VisualStudio/feedback/SearchResults.aspx?SearchQuery=CustomAttributeData

CustomAttributeData.GetCustomAttributes throws exception when type has a WebService attribute
Opened By  GaboG 
ID  161522
Status  Closed
Resolution  Fixed
Opened  7/11/2006
Closed  10/16/2006

CustomAttributeData throws when attribute has a public Enum property
Opened By  Fabian Schmied 
ID  296032
Status  Active
Opened  8/31/2007

CustomAttributeData does not have a GetCustomAttributes overload for type
Opened By  RichardGrimes 
ID  98478
Status  Closed
Resolution  By Design

CustomAttributeData for SecurityPermission Constructor does not contain arguments that match it's signature
--------------------------------------------------------------------------------
When I retrieve CustomAttributeData for a SecurityAttribute, the arguments are missing and don't match the signature of the constructor for the SecurityAttribute.
--------------------------------------------------------------------------------
Opened By  nywarrior 
ID  94803
Status  Closed
Resolution  Not Reproducible

Only issue #2 is still marked as active and I was able to reproduce it. This issue is caused by the fact that System.Enum type returns false for its IsEnum method and IsValueType is false as well :):).

I can see the design where using of the Enum type field for the attribute can be pretty alright. [CommonAttribute(MyEnum.MyTypeId)] where CommonAttribute is located in the common library and developer uses her library enum member.

Wrapping it up for a moment here, enough blah for the CustomAttributeData, hopefully enough material for Mark to review the applicability for Spring.NET 1.1.

1 comment:

Anonymous said...

peterritchie is very, very smart guy