2

let's say I have 2 classes like this:

public class Foo
{
[Required]
public string Name {get;set;}
}

public class Bar 
{
// put here [Required] at run-time
public string Name {get;set;}
}

var foo = new Foo();
var bar = new Bar();
//copy the required from foo to bar

is it possible to copy the attributes from foo to bar at run-time ?

Omu
  • 69,856
  • 92
  • 277
  • 407
  • Just to make sure, do you mean to the value of Name or do you mean to the attribute decorating Name property? The output you wish is that Bar.Name will equal to Foo.Name or that Bar.Name will be decorated with [Required]? – Elisha Jun 14 '10 at 14:03
  • @Elisha Bar.Name will be decorated with Required – Omu Jun 14 '10 at 14:07

7 Answers7

8

Attributes aren't attached to instances -- they're attached to type definitions.

While you can create new types at runtime using reflection, you cannot change existing type definitions.

dtb
  • 213,145
  • 36
  • 401
  • 431
4

The notion of "copying" attributes is out. However, you can do something meaningful in the code that checks if the attribute is applied. You could use another attribute that tells the code that it should use another type to verify for the [Required] attribute. For example:

[AttributeUsage(AttributeTargets.Class)]
public class AttributeProviderAttribute : Attribute {
    public AttributeProviderAttribute(Type t) { Type = t; }
    public Type Type { get; set; }
}

Which you'd use like this:

public class Foo {
    [Required]
    public string Name { get; set; }
}

[AttributeProvider(typeof(Foo))]
public class Bar {
    public string Name { get; set; }
}

The code that checks for the attribute could look like this:

    static bool IsRequiredProperty(Type t, string name) {
        PropertyInfo pi = t.GetProperty(name);
        if (pi == null) throw new ArgumentException();
        // First check if present on property as-is
        if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).Length > 0) return true;
        // Then check if it is "inherited" from another type
        var prov = t.GetCustomAttributes(typeof(AttributeProviderAttribute), false);
        if (prov.Length > 0) {
            t = (prov[0] as AttributeProviderAttribute).Type;
            return IsRequiredProperty(t, name);
        }
        return false;
    }

Note how this code allows the attribute provider to be chained.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
3

Whether this is possible depends on which libraries need to see the attribute. If the code that needs to see this uses reflection, then you're scuppered. You can't do it.

However; if the code that needs this uses the component model, it is possible - but it is a lot of work. You could implement a TypeDescriptionProvider that creates a per-instance ICustomTypeDescriptor, and defines custom-chained PropertyDescriptor instances. You would then supplement (or replace) the attribute(s) per-property, passing them into the base-constructor (or override the attributes property). The upshot is that the following will then include your attribute:

var attribs = TypeDescriptor.GetProperties(obj)["Name"].Attributes;

Things like winforms data-binding use this API, but it won't care much about your custom attribute. You'll excuse me not writing a full example, but that is a lot of work; none of those interfaces / base-types is trivial to implement. Ultimately, I doubt it is worth it.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

Attributes are a part of the meta-data of the (compiled and loaded) assembly, so I don't think you could modify them at runtime easily.

The only option I can think of is generating code with the attribute using CodeDOM and re-compiling it (and re-loading the assembly), or doing the same thing using System.Reflection.Emit (which would be possible, but very complicated).

Why do you want to do this? Perhaps there is an easier way to solve your problem...

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • well, basically I just want to know if it is possible to decorate with attributes at runtime before or after creation of an instance of some type – Omu Jun 14 '10 at 14:10
  • 1
    @Omu: No. At least without a lot of reflection magic (which is used for example by various proxies that automatically implement interfaces etc.). But would there be any practical usage of doing that? – Tomas Petricek Jun 14 '10 at 14:35
  • so it is possible, all we need now is someone that knows how to do this; practical ? well yes, if you need to decorate some properties at runtime, than that would help ya – Omu Jun 14 '10 at 18:44
  • @Omu: There would be a lot of limitations, but depending on the use, reflection may solve the problem. That's why I'm asking about some specific information - I understand you want to decorate properties at runtime. I just don't understand why... – Tomas Petricek Jun 14 '10 at 19:54
  • something like this: http://stackoverflow.com/questions/2916808/asp-net-mvc-2-view-model-model-validation-is-there-a-way-to-map-validation – Omu Jun 15 '10 at 05:39
0

If you need attributes to perform data binding or other task related to UI, you may try to alter default behavior of TypeDescriptor.

Looks here http://msdn.microsoft.com/en-us/library/ms171819.aspx

You may add your custom type descriptor for type, and it allows you provide custom attributes to some components that uses TypeDescriptor.GetXXX members instead of operating directly with type metadata.

STO
  • 10,390
  • 8
  • 32
  • 32
0

Am I missing the point here? Wy not use an implicit operator?

Bus bus;
BigVehicle big = bus;

public static implicit operator Bigvehicle(Bus bus)
{

}
takrl
  • 6,356
  • 3
  • 60
  • 69
Byron
  • 691
  • 9
  • 9
-5

Please have a look at AutoMapper. AutoMapper is a mapper framework that can convert DTO objects to domain model objects.

Introduction info: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx

Binary release site: http://automapper.codeplex.com

Source code release site: http://code.google.com/p/automapperhome/