Reputation: 183
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
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