Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass typeof(x) type to generic method

Tags:

c#

generics

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.

like image 712
expenguin Avatar asked Jan 18 '26 09:01

expenguin


1 Answers

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.

like image 126
Mike Hofer Avatar answered Jan 19 '26 22:01

Mike Hofer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!