C
C#2mo ago
Leroico

✅ Getting method parameters with reflection on library code

Hi everyone, so I'm making a wrapper/library for a rest api, and to trying to simplify the code i ended up using reflection to get a method's parameters, something like this:
async Task<T> GetAsync(string service, ParameterInfo[] parameters, params object[] values)
{
// make dictionary from parameters and values
Dictionary<string, string> args = ...

// make the http request and return the response
HttpRequestMessage request = new(HttpMethod.Get, $"{service}?{string.Join('&', args.Select(x => $"{x.Key}={x.Value}"))}");
...
}

// here's where i'm using reflection
async Task<Model1> Example1(int arg1, int arg2, string arg3) =>
await GetAsync<Model1>("service1", MethodBase.GetCurrentMethod().GetParameters(), arg1, arg2, arg3);

async Task<Model2> Example2(double arg1, char arg2) =>
await GetAsync<Model2>("service2", MethodBase.GetCurrentMethod().GetParameters(), arg1, arg2);
async Task<T> GetAsync(string service, ParameterInfo[] parameters, params object[] values)
{
// make dictionary from parameters and values
Dictionary<string, string> args = ...

// make the http request and return the response
HttpRequestMessage request = new(HttpMethod.Get, $"{service}?{string.Join('&', args.Select(x => $"{x.Key}={x.Value}"))}");
...
}

// here's where i'm using reflection
async Task<Model1> Example1(int arg1, int arg2, string arg3) =>
await GetAsync<Model1>("service1", MethodBase.GetCurrentMethod().GetParameters(), arg1, arg2, arg3);

async Task<Model2> Example2(double arg1, char arg2) =>
await GetAsync<Model2>("service2", MethodBase.GetCurrentMethod().GetParameters(), arg1, arg2);
Now i've heard that reflection is pretty inefficient, so considering that this is library code that other people might end up using, is this a bad idea? should i try another, maybe more efficient, method? btw i have no idea what tags i should add to this
33 Replies
sibber
sibber2mo ago
why not have the user pass in a collection of arguments?
Leroico
LeroicoOP2mo ago
you mean asking the user for the arguments?
sibber
sibber2mo ago
or create a strongly typed object with all the possible arguments for each endpoint depends on the api if thats a good idea or not yeah what youre doing now seems too convoluted for no apparent benefit to me
Leroico
LeroicoOP2mo ago
its wrapping a weather api, so the idea is that there are methods like GetPastWeather() or GetCurrentWeather() and the user passes (for example) the coordinates of the location, so i'm not sure how i would implement that
sibber
sibber2mo ago
method overloads one for coordinates, one for location name, etc
Leroico
LeroicoOP2mo ago
ok i get you that was my initial idea
Sehra
Sehra2mo ago
or simply GetAsync<T>(string service, IDictionary<string, object> values), or string,string if you want to format the values in Example1/Example2
Leroico
LeroicoOP2mo ago
that's what i was doing, but in every example method i needed to create a new dictionary, while hardcoding the names of the parameters there's not really a problem with that
sibber
sibber2mo ago
all you need is IEnumerable<KeyValuePair<TKey,TValue>>
Leroico
LeroicoOP2mo ago
but i was trying to repeat less code
sibber
sibber2mo ago
you can create an overload that takes a span to avoid allocs if youre on .net 9 you can use params with that
Leroico
LeroicoOP2mo ago
i'm on .net 8
sibber
sibber2mo ago
repeating less isnt always better
Sehra
Sehra2mo ago
i'd also change the query string creation to escape the keys/values properly
sibber
sibber2mo ago
people follow DRY too religiously
Leroico
LeroicoOP2mo ago
how would i do that?
sibber
sibber2mo ago
and in a lot of cases end up with way less readable or overengineered code url encode
Leroico
LeroicoOP2mo ago
ok i'll be doing that next
sibber
sibber2mo ago
although iirc HttpClient should handle that but dont quote me
Leroico
LeroicoOP2mo ago
i don't know if this image is readable but this is the code i'm using to send the request
No description
Leroico
LeroicoOP2mo ago
just to clear anything up so in this case getparameters() is kind of overkill?
Sehra
Sehra2mo ago
think it should be $"{Uri.EscapeDataString(x.Key)}={Uri.EscapeDataString(x.Value)}"
sibber
sibber2mo ago
use GetFromJsonAsync but method overloads seem like the best option here definitely thats not what reflection is intended for
Leroico
LeroicoOP2mo ago
ok thanks for the help i'll use that thanks do i need to escape the key if i'm going to be hardcoding them?
Sehra
Sehra2mo ago
no, then you know what they are
sibber
sibber2mo ago
hardcode the url encoded version
Leroico
LeroicoOP2mo ago
alright thanks again for the help
sibber
sibber2mo ago
np
Leroico
LeroicoOP2mo ago
btw if i configured my httpclient with a baseurl that will still work with GetFromJsonAsync right just making sure
sibber
sibber2mo ago
yeah
Leroico
LeroicoOP2mo ago
nice do i delete the post now?
sibber
sibber2mo ago
$close
MODiX
MODiX2mo ago
If you have no further questions, please use /close to mark the forum thread as answered

Did you find this page helpful?