I've made some Middleware that logs all actions taken by a user within my application. Depending on the action taken, I need parse out some [FromBody] JSON into their respective key/value pairs for logging.
I need to deserialize my JSON within the middleware, but in order to do that, I need to send my DtoType along to the deserializer in order for it to parse out my key/values. I've got a method setup to do that, but I need to pass in a generic type because this will be different for every single action the user takes. (e.g. I have a UserDto, CustomerDto, etc...)
I've setup a dictionary in order to get the type that I need, however when I pass the var to my logging method to do the rest of the work, I get an error stating that this is not a type but a variable. This is true, however I have no idea how I'm supposed to get the type that I pulled out of my dictionary into the method generic type.
See my code below:
LoggingMiddleware.cs readonly dictionary
private readonly Dictionary<string, Type> _postDictionary = new Dictionary<string, Type>
{
{ "path/customers", typeof(CustomerPostDto) },
...//More entries//...
};
LoggingMiddleware.cs Invoke Method
public async Task Invoke(HttpContext context)
{
using (var streamCopy = new MemoryStream())
{
...//Do some stuff here//...
//Logging Actions
if (request.Path != "/")
{
if (request.Method == "POST")
{
Type T = _postDictionary[path];
logAction<T>(contextDto);
}
}
...//Do some stuff here//...
}
}
LoggingMiddleware.cs logAction Method
private void logAction<T>(object contextDto)
{
var dto = ControllerBase.ParseBody<T>(contextDto.Body);
...//Do some stuff here//...
}
EDIT: Following Example of Possible Duplicate - updated code
if (request.Method == "POST")
{
Type T = _postDictionary[path];
MethodInfo methodLogAction = typeof(LoggingMiddleware).GetMethod("logAction", BindingFlags.NonPublic);
MethodInfo generic = methodLogAction.MakeGenericMethod(T);
generic.Invoke(contextDto, null);
}
The above never returns anything for GetMethod other than null.
The exception is telling you exactly what is wrong.
Type T = _postDictionary[path];
This line of code pulls a Type instance from the dictionary and stores it in the variable, T. Then, you try to use it like this:
logAction<T>(contextDTO);
However, a generic method expects a non-variable argument between the angle-brackets. Types don't change at run-time; but the type arguments to a generic method can. (There are some compiler-specific nuances to that statement, but we'll ignore those for now.)
What you're essentially trying to get at is this:
logAction<SomeType>(contextDTO);
But if you want to store the type in a Dictionary, you'll have to pass that type as an argument to your method, and lose the generic capability:
public void logAction(Type type, object data)
{
// Log the data here
};
This is because the value of T is only known at runtime, not at compile time. You're going to have to reflect over T to get at its properties (as your question implies). In that event, you likely don't want a generic method, anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With