0

I've been searching for a while now and tested several methods, but i didn't find the answer i was looking for. I'll try to explain.

I have an object with several fields/properties. These properties have custom attributes. What i want is to get the custom attribute from a specific propertie without all the knowlege of the object.

The are the base classes

// FieldAttr has a public Text propery

public class TestObject  
{
    // Declare fields
    [FieldAttr("prop_testfld1")]
    public FLDtype1 testfld1 = new FLDtype1();

    [FieldAttr("prop_testfld2")]
    public FLDtype2 testfld2 = new FLDtype2();

    [FieldAttr("prop_testfld3")]
    public FLDtype1 testfld3;
}

public class FLDtype1
{
    public string Value { get; set; }
}

public class FLDtype2
{
    public Guid Value { get; set; }
}

public sealed class FieldAttr: System.Attribute
{
    private string _txt;

    public EntityFieldType(string txt)
    {
        this._text = txt;
    }

    public string Text { get { return this._text; } }
}

And i want to be able to do this in my application:

static void Main(string[] args)
{
    TestObject test = new TestObject();

    // (Option 1: preferred)
    Console.WriteLine(test.testfld1.getFieldAttr().Text);

    // (Option 2)
    Console.WriteLine(test.getFieldAttr(test.testfld1).Text);
}

Is this possible? I've seen methods to get custom attribute values from all properties/fields of an object, but not for a specific field.

I've got a working method to get custom attribute from an enum, but wasn't able to recreate it for object fields/properties. This is because i couldn't get the name of the field i was trying to explore, because (for example) test.testfld1.ToString() give's me "ns.FLDtype1".

Looking forward for the answer :) (and excuse my english)

apxcode
  • 7,696
  • 7
  • 30
  • 41
user2916010
  • 11
  • 1
  • 4
  • Have you tried this way? [link](http://stackoverflow.com/questions/6538366/access-to-the-value-of-a-custom-attribute) – d_z Apr 27 '14 at 21:32
  • yeah. The problem is that the GetMethod("")/GetField("") requires a string name of the field. And i can't get that. – user2916010 Apr 27 '14 at 21:50
  • I don't want to give the name. I want the field to return its own custom attributes. if i can do that, i can create an even more dynamic way to handle the fields. The given example is a simple representation of what i want to do. – user2916010 Apr 27 '14 at 22:21

2 Answers2

1

Yes it is possible:

public static class Extensions
{
    public static FieldAttr GetFieldAttr(
        this TestObject source,
        Expression<Func<TestObject,object>> field)
    {
        var member = field.Body as MemberExpression;
        if (member == null) return null; // or throw exception

        var fieldName = member.Member.Name;

        var test = typeof (TestObject);
        var fieldType = test.GetField(fieldName);
        if (fieldType != null)
        {
            var attribute = fieldType.GetCustomAttribute<FieldAttr>();

            return attribute;
        }

        return null;
    }
}

Usage:

TestObject test = new TestObject();

var attr = test.GetFieldAttr(x => x.testfld3);

if(attr != null) Console.WriteLine(attr.Text);

Here is the fiddle

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • This works if i only declare one field/property of type FLDtype1. if i declare 2, i only get the first one every time. In the fiddle, Console.WriteLine(test.testfld3.GetFieldAttr().Text) returns "prop_testfld1" while it should return "prop_testfld3" – user2916010 Apr 27 '14 at 22:47
  • this is where i got stuck – user2916010 Apr 27 '14 at 22:48
  • @user2916010 ah, you are right.Sorry, I have just updated my answer. try again.I have also updated the [fiddle](http://dotnetfiddle.net/c39vNl) – Selman Genç Apr 27 '14 at 22:59
  • Also tried this one, but i am trying to make it smarter. This ajustment means i can't call the getFieldAttr from the field itself. (test.testfld3.getFieldAttr()). – user2916010 Apr 27 '14 at 23:06
1

After another day of trial and error I decided to make use of Selman22 answer with a little modification. This is code I created:

public class TestObject : iTestObject 
{
    // Declare fields
    [FieldAttr("prop_testfld1")]
    public FLDtype1 testfld1 = new FLDtype1();

    [FieldAttr("prop_testfld2")]
    public FLDtype2 testfld2 = new FLDtype2();

    [FieldAttr("prop_testfld3")]
    public FLDtype1 testfld3;
}

public class FLDtype1 : iField
{
    public string Value { get; set; }
}

public class FLDtype2 : iField
{
    public Guid Value { get; set; }
}

public sealed class FieldAttr: System.Attribute
{
    private string _txt;

    public FieldAttr(string txt)
    {
        this._txt = txt;
    }

    public string Text { get { return this._txt; } }
}

public interface iField { }
public interface iTestObject { }

public static class Extensions
{
    public static FieldAttr GetFieldAttr<T>(this T source, Expression<Func<iField>> field) where T : iTestObject 
    {
        // Get member body. If no body present, return null
        MemberExpression member = (MemberExpression)field.Body;
        if (member == null) { return null; }

        // Get field info. If no field info present, return null
        FieldInfo fieldType = typeof(T).GetField(member.Member.Name);
        if (fieldType == null) { return null; }

        // Return custom attribute
        return fieldType.GetCustomAttribute<FieldAttr>();
    }
}

Usage:

public class Program
{
    public static void Main()
    {
        TestObject test = new TestObject();
        Console.WriteLine(test.GetFieldAttr(() => test.testfld1).Text);
        Console.WriteLine(test.GetFieldAttr(() => test.testfld2).Text);
        Console.WriteLine(test.GetFieldAttr(() => test.testfld3).Text);
    }
}

Uses:

using System;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;

I have implemented interfaces to protect the GetFieldAttr method

@Sulman22: Thnx for the response!

user2916010
  • 11
  • 1
  • 4
  • One thing I'd like to add to @user2916010 's answer is that sometimes you will get this exception: Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.MemberExpression'. So before using this solution please look at this post for the correct way of accessing the member body: http://stackoverflow.com/questions/12420466/unable-to-cast-object-of-type-system-linq-expressions-unaryexpression-to-type – Sal May 03 '17 at 19:16