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)

3
  • Have you tried this way? link Commented Apr 27, 2014 at 21:32
  • yeah. The problem is that the GetMethod("")/GetField("") requires a string name of the field. And i can't get that. Commented Apr 27, 2014 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. Commented Apr 27, 2014 at 22:21

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

4 Comments

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"
this is where i got stuck
@user2916010 ah, you are right.Sorry, I have just updated my answer. try again.I have also updated the fiddle
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()).
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!

1 Comment

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: stackoverflow.com/questions/12420466/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.