Britton
Britton

Reputation: 183

How can I read method parameter information (names and values) from an attribute class in .NET

I'm building a cool custom HttpClient wrapper that will using Attributes to build dynamic routes etc. I'm having a problem figuring out how to access the method parameter values from the attribute of the method. Here is an example of a method with my custom Attribute:

[RestEndpoint("appointment/{appointmentId}")]
public AppointmentDto GetAppointmentById(int appointmentId)
{
    //code calls base class methods to hit the endpoint defined in this method's attribute 
}

Below is my attribute class. In my attribute class, I want to read the parameters of the method it is attached to and in the GetDynamicEndpoint() method, build the Uri doing some replace and regex sugar.

I can't seem to figure out how to actually get the method information that a given Attribute is attached to. I can do the opposite (read attribute info from the method).

[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class RestEndpoint : Attribute
{
    public HttpVerb Verb { get; set; }

    public string Uri { get; set; }

    public RestEndpoint(string uri)
    {
        Verb = HttpVerb.Get;
        Uri = uri;
    }

    public RestEndpoint(HttpVerb verb, string uri)
    {
        Verb = verb;
        Uri = uri;
    }

    public string GetDynamicEndpoint()
    {
        //get method for this attribute and read it's parameters
        //in order to build dynamic endpoint based on method's parameter values          

        return "dynamic endpoint";
    }

}

Upvotes: 1

Views: 2085

Answers (1)

Britton
Britton

Reputation: 183

So from the comments and research, what I am trying to do here is impossible with current built-in .Net framework capabilities. However, I did take @Eugene's advice and passed in the parameters from the method to the attribute to build the dynamic route. Ended-up something like this:

[UseRestEndpoint("appointment/{first}/{last}")]
public AppointmentDto GetAppointmentById(string first, string last)
{
    return Send<AppointmentDto>(new { first, last });
}

And the Attribute call that builds the dynamic route uri from the passed in dynamic object:

public string GetDynamicEndpoint(dynamic parameters)
{
    if (!Uri.Contains("{") && !Uri.Contains("}"))
        return Uri;

    var valueDictionary = GetUriParameterValueDictionary(parameters);

    string newUri = Uri;
    foreach (KeyValuePair<string, string> pair in valueDictionary)
        newUri = newUri.Replace(string.Format("{{{0}}}", pair.Key), pair.Value);

    return newUri;
}

private Dictionary<string, string> GetUriParameterValueDictionary(object parameters)
{
    var propBag = parameters.ToPropertyDictionary();
    return GetUriParameters().ToDictionary(s => s, s => propBag[s]);
}


private IEnumerable<string> GetUriParameters()
{
    Regex regex = new Regex(@"(?<={)\w*(?=})");
    var matchCollection = regex.Matches(Uri);

    return (from Match m in matchCollection select m.Value).ToList();
}

This isn't all the implementation code for this to work, but it is what ended up getting the concept to work. Thanks everyone for the comments.

Upvotes: 2

Related Questions