Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Attributes on Class Members

I am using a Custom Attribute to define how a class's members are mapped to properties for posting as a form post (Payment Gateway). I have the custom attribute working just fine, and am able to get the attribute by "name", but would like to get the attribute by the member itself.

For example:

getFieldName("name");

vs

getFieldName(obj.Name);

The plan is to write a method to serialize the class with members into a postable string.

Here's the test code I have at this point, where ret is a string and PropertyMapping is the custom attribute:

foreach (MemberInfo i in (typeof(CustomClass)).GetMember("Name"))
{
    foreach (object at in i.GetCustomAttributes(true))
    {
        PropertyMapping map = at as PropertyMapping;
        if (map != null)
        {
            ret += map.FieldName;
        }
    }
}

Thanks in advance!

like image 214
ccook Avatar asked Mar 10 '09 14:03

ccook


People also ask

Can we make your own custom attributes?

If you want to define your own custom attributes in HTML, you can implement them through data-* format. * can be replaced by any of your names to specify specific data to an element and target it in CSS, JavaScript, or jQuery. There are some rules to keep in mind before defining your custom attributes.

What are custom attributes?

A custom attribute is a property that you can define to describe assets. Custom attributes extend the meaning of an asset beyond what you can define with the standard attributes. You can create a custom attribute and assign to it a value that is an integer, a range of integers, or a string.

How do I add custom attributes to my framework?

AttributeUsage has a named parameter, AllowMultiple , with which you can make a custom attribute single-use or multiuse. In the following code example, a multiuse attribute is created. In the following code example, multiple attributes of the same type are applied to a class. [Author("P.

How would you define a custom attribute that can only be applied to class code elements?

The following code fragment specifies that a custom attribute can be applied to any class or method: C# Copy. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] End Class.


1 Answers

You can't really do this, unless you're using C# 3.0 in which case you'll need to rely on LINQ (ehm, expression trees).

What you do is that you create a dummy method for a lambda expression which lets the compiler generate the expression tree (compiler does the type checking). Then you dig into that tree to get the member. Like so:

static FieldInfo GetField<TType, TMemberType>(
    Expression<Func<TType, TMemberType>> accessor)
{
    var member = accessor.Body as MemberExpression;
    if (member != null)
    {
        return member.Member as FieldInfo;
    }
    return null; // or throw exception...
}

Given the following class:

class MyClass
{
    public int a;
}

You can get the meta data like this:

// get FieldInfo of member 'a' in class 'MyClass'
var f = GetField((MyClass c) => c.a); 

With a reference to that field you can then dig up any attribute the usual way. i.e. reflection.

static TAttribute GetAttribute<TAttribute>( 
    this MemberInfo member ) where TAttribute: Attribute
{
    return member.GetCustomAttributes( typeof( TAttribute ), false )
        .Cast<TAttribute>().FirstOrDefault<TAttribute>();
}

Now you can dig up an attribute on any field by something which is in large checked by the compiler. It also works with refactoring, if you rename 'a' Visual Studio will catch that.

var attr = GetField((MyClass c) => c.a).GetAttribute<DisplayNameAttribute>();
Console.WriteLine(attr.DisplayName);

There's not a single literal string in that code there.

like image 170
John Leidegren Avatar answered Oct 11 '22 18:10

John Leidegren