C
C#4d 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
sibber4d ago
why not have the user pass in a collection of arguments?
Leroico
LeroicoOP4d ago
you mean asking the user for the arguments?
sibber
sibber4d 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
LeroicoOP4d 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
sibber4d ago
method overloads one for coordinates, one for location name, etc
Leroico
LeroicoOP4d ago
ok i get you that was my initial idea
Sehra
Sehra4d 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
LeroicoOP4d 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
sibber4d ago
all you need is IEnumerable<KeyValuePair<TKey,TValue>>
Leroico
LeroicoOP4d ago
but i was trying to repeat less code
sibber
sibber4d 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
LeroicoOP4d ago
i'm on .net 8
sibber
sibber4d ago
repeating less isnt always better
Sehra
Sehra4d ago
i'd also change the query string creation to escape the keys/values properly
sibber
sibber4d ago
people follow DRY too religiously
Leroico
LeroicoOP4d ago
how would i do that?
sibber
sibber4d ago
and in a lot of cases end up with way less readable or overengineered code url encode
Leroico
LeroicoOP4d ago
ok i'll be doing that next
sibber
sibber4d ago
although iirc HttpClient should handle that but dont quote me
Leroico
LeroicoOP4d 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
LeroicoOP4d ago
just to clear anything up so in this case getparameters() is kind of overkill?
Sehra
Sehra4d ago
think it should be $"{Uri.EscapeDataString(x.Key)}={Uri.EscapeDataString(x.Value)}"
sibber
sibber4d ago
use GetFromJsonAsync but method overloads seem like the best option here definitely thats not what reflection is intended for
Leroico
LeroicoOP4d 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
Sehra4d ago
no, then you know what they are
sibber
sibber4d ago
hardcode the url encoded version
Leroico
LeroicoOP4d ago
alright thanks again for the help
sibber
sibber4d ago
np
Leroico
LeroicoOP4d ago
btw if i configured my httpclient with a baseurl that will still work with GetFromJsonAsync right just making sure
sibber
sibber4d ago
yeah
Leroico
LeroicoOP4d ago
nice do i delete the post now?
sibber
sibber4d ago
$close
MODiX
MODiX4d ago
If you have no further questions, please use /close to mark the forum thread as answered

Did you find this page helpful?