views:

238

answers:

7

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 ?

+8  A: 

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
+2  A: 

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
@Tomas Petricek 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
@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
@Tomas Petricek 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
@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
@Tomas Petricek something like this: http://stackoverflow.com/questions/2916808/asp-net-mvc-2-view-model-model-validation-is-there-a-way-to-map-validation
Omu
A: 

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
+3  A: 

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
+3  A: 

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
@Omu: thanks for the answer mark. You have to assign the bounty separately: http://blog.stackoverflow.com/2010/06/improvements-to-bounty-system/
Hans Passant
A: 

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/

Vapour in the Alley
A: 

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

Bus bus; BigVehicle big = bus;

public static implicit operator Bigvehicle(Bus bus) {

}

Byron