7

Is it somehow possible to extend a type, wich is defined in another assembly, to add an attribute on one of its properties?

Exemple I have in assembly FooBar:

public class Foo
{
   public string Bar { get; set; }
}

But in my UI assembly, I want to pass this type to a third party tool, and for this third party tool to work correctly I need the Bar property to have a specific attribute. This attribute is defined in the third party assembly, and I don't want a reference to this assembly in my FooBar assembly, since FooBar contains my domain an this is a UI tool.

Johnny5
  • 6,664
  • 3
  • 45
  • 78
  • what do you mean by attribute? Like [DataMember] (WCF) attribute? – Mark W Nov 29 '11 at 19:58
  • You'll have to wait for .NET 4.5 and its CustomReflectionContext class. – Hans Passant Nov 29 '11 at 20:11
  • @Hans Passant, if the third party tool uses the `TypeDescriptor` API this is already possible as explained in my answer. – João Angelo Nov 29 '11 at 20:13
  • 1
    If like me you're here because you want to specify a custom editor for a type in PropertyGrid, read this question instead http://stackoverflow.com/questions/849202/how-do-i-inject-a-custom-uitypeeditor-for-all-properties-of-a-closed-source-type – Colonel Panic Sep 24 '12 at 15:54

4 Answers4

9

You can't, if the thirdy-party tool uses standard reflection to get the attributes for your type.

You can, if the third-party tool uses the TypeDescriptor API to get the attributes for your type.

Sample code for the type descriptor case:

public class Foo
{
    public string Bar { get; set; }
}

class FooMetadata
{
    [Display(Name = "Bar")]
    public string Bar { get; set; }
}

static void Main(string[] args)
{
    PropertyDescriptorCollection properties;

    AssociatedMetadataTypeTypeDescriptionProvider typeDescriptionProvider;

    properties = TypeDescriptor.GetProperties(typeof(Foo));
    Console.WriteLine(properties[0].Attributes.Count); // Prints X

    typeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(
        typeof(Foo),
        typeof(FooMetadata));

    TypeDescriptor.AddProviderTransparent(typeDescriptionProvider, typeof(Foo));

    properties = TypeDescriptor.GetProperties(typeof(Foo));
    Console.WriteLine(properties[0].Attributes.Count); // Prints X+1
}

If you run this code you'll see that last console write prints plus one attribute because the Display attribute is now also being considered.

João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • Can you explain further about `TypeDescriptor` ? – Johnny5 Nov 29 '11 at 20:03
  • I added sample code that can be used to extend a types attributes if the consumer relies on the TypeDescriptor API. You need to assert if the tool uses that API or not, you could do it with Reflector or just ask the vendor. – João Angelo Nov 29 '11 at 20:12
  • I didn't think of that before asking, but is it the same as using the `MetadataType` attribute? – Johnny5 Nov 29 '11 at 20:20
  • The use of the `Display` in the sample code was just for illustration purposes, it's applicable to other attributes. – João Angelo Nov 29 '11 at 20:47
1

No. It's not possible to add attributes to types from separate assemblies.

What you can do, though, is create your own type that wraps the third-party type. Since you have full control over your wrapper class, you can add the attributes there.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
0

What about:

public class Foo
{
    public virtual string Bar
}

public class MyFoo : Foo
{
     [yourcustomattribute]
     public overrides string Bar
}
Maess
  • 4,118
  • 20
  • 29
0

What I think you need is some kind of adapter layer that will not let that infrastructure dependency leak into your domain logic. Maybe you can create an adapter class that will be like a data transfer object to the other technology. This class lives in an integration assembly that has a dependency on the 3rd party library:

public class FooDTO {
   [TheirAttribute]
   public string Bar { get; set; }
}

You can then use something like AutoMapper to ease the pain of changing representations.

The ideal solution, though, is if the 3rd party library supported additional ways to provide metadata about their operations. Maybe you can ask them for this feature.

Jordão
  • 55,340
  • 13
  • 112
  • 144