Implementing Generic Type Inference in C# reflecti

2020-03-26 20:28发布

I need to do some generic type inference for a scripting language implementation and I am wondering if I am missing some straightforward approach. For the moment let me just ask about type structure and ignore bounds. To illustrate, here is a deeply nested example:

T foo<T>( List<List<List<T>>> ) {...}

Now I want to test if I can pass an argument bar of type:

List<List<List<string>>>

to that method and later use MakeGenericMethod() with the discovered param type to reify and invoke it.

From what I can tell, even if I manage to construct an open generic type equivalent to the foo argument (i.e. List<List<List<T>>>), it will not test with isAssignable(). I'm not sure if there is some trick to checking the assignability of open generic types or if it's simply not supported. I guess if I have to I can do this directly.

On the reification - It looks like I'm going to have to recursively crawl through the types to find the argument type that matches the location of the type parameter and then do the substitution... I had been hoping that I might be able to somehow construct the invocable method from the argument type more directly, but I'm not seeing how to do this.

Any advice from someone who's already gone through this madness would be appreciated :)

thanks, Pat Niemeyer

1条回答
成全新的幸福
2楼-- · 2020-03-26 21:08

So, I believe I have implemented this successfully going on the assumption that you have to reify the types for assignability comparison. As near as I can tell there is not even a way to extract the base type from a generic type in order to perform assignment checks yourself. So what I ended up doing is using GetGenericArguments to traverse the method parameter type and the argument type in parallel, performing sanity checks at each step (number of generic params match, etc.) and once ultimately finding the "naked" generic type param, noting the corresponding (inferred) type in the argument. You can determine that you've found a type param using IsGenericParameter. Then, weirdly, you have to save those types aside and use them to instantiate the method by passing them in a particular order to MakeGenericMethod. The order is provided for you by a property on Type itself, GenericParameterPosition, (again, weird) but a simple orderby sorts them out. After that all of the normal rules seem to apply.

-Pat

查看更多
登录 后发表回答