-
Notifications
You must be signed in to change notification settings - Fork 531
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
.Net 6 + Ninject 3.3.4: InvalidProgramException when using delegates for initializing constructor parameters #389
Comments
As was diagnosed in dotnet/runtime#67351 it's some invalid IL Ninject produces that wasn't properly validated in .NET 5.0 so it somehow worked (most likely could crash at a random point) |
It's treating all parameters as object it appears, which probably close to where the problem is.
This code uses |
This looks relevant: Ninject/src/Ninject/Injection/ExpressionInjectorFactory.cs Lines 116 to 118 in 3ff6bda
So that's not handling boxing or unboxing pointer types, which don't behave like value types. snippet I'm not even sure why this repro uses a pointer constructor overload to string, so that might be something to look into. It could be something in metadata enumeration order caused it to start using that constructor when it didn't before. That's a common problem folks run into with loosely constrained uses of reflection. |
The problem seems to come because it's trying to stuff everything into object[]. Wonder if we can avoid the whole problem by generating a dynamic lambda signature to use for the generic argument to |
IMO you need to really understand why you're using the pointer constructor and if that's intentional before going down the path of supporting calling methods that use pointers. For example, if calling a method that takes pointer will never work (and never worked previously) maybe those methods should be excluded. |
@bartdesmet mentioned on another thread that ninject looks at all constructors and adds them to the plan just in case they might be needed. This includes things that might never work. I was able to throw together a hack fix for your issue here: ericstj@155383f Probably a better solution would be to make ninject consider this in its https://github.com/ninject/Ninject/blob/3ff6bdaad8cde418724b8b18edb3a457b9785f8e/src/Ninject/Selection/Selector.cs to exclude constructors, methods, and perhaps other things which it cannot generate code for. There are probably other new language things like ref struct parameters that it cannot support as well. |
To try and avoid the constructor enumeration I was hoping that making the string both constants Yup the hack does work. |
I thought of another workaround. If you can avoid adding strings but instead create a wrapping type that might avoid this problem. Something like:
Then add a constructor parameter that accepts that. That might avoid Ninject trying to generate the expressions that handle string constructors that it never uses. |
Thanks for the suggestion. The same problem exists with methods and I presume properties. i.e. it enumerates and generates code replacements for them. I fixed it for constructors and methods using the hack, but now there is another case of To try and find where this is defined, I had to rebuild two extension libraries with my local build of Ninject ( At this point I think this making a fix to Ninject may not be a possible solution. |
Just want to mention that Ninject 3.3.4 uses IL Emit whereas the main branch uses ExpressionTree |
@scott-xu Which branch is considered current / which did 3.3.4 get built from? |
@scott-xu I have a patch based on the 3.3.4 tag. What is the best branch to submit a PR to with the fix? Any possibly of releasing an update? The fix is here: https://github.com/nschuessler/Ninject/tree/nschuessler/net6
|
What about emit |
You are asking about the (object) argument really being a pointer? My understanding that casting anything to an Let's see of @EgorBo would be able to clarify if there are exceptions or cases that do work maybe like the above. btw. Good catch. I didn't fix that one if it is needed. |
@scott-xu it appears we are not getting an answer on this. In .Net 6 they have added more checks on the generated IL than previous versions. The way to answer if changes are needed may be to build a .Net 6.0 specific version as a test and then see if there are any exceptions. To ensure the IL is jitted, I believe run it under Visual Studio (press F5) with the profiler running (which causes all the check to happen). This is how I verified my fix. |
@nschuessler Can you please try this build please? |
Just noticed another problem at .NET 6. No idea what's going on. It is just to unbox a value type.
|
Will try this today. |
Sadly it doesn't seem to work. Same issue, unless I goofed something. Can you point me to the code change for this release? Maybe I can spot something |
(For the other issue) If we can find a small repro we can post it on dotnet/runtime project for help. May help to show the signature of the method being generated. |
Check this commit please 8624475 |
That test passes on your system? I don't know enough about IL to spot an issue. I'll open an issue on dotnet/runtime and point it at this thread. |
Try CI 269 please: https://ci.appveyor.com/project/Ninject/ninject/builds/43200302/artifacts |
Yes, this one works (just testing the string constructor though). |
@scott-xu When I made a custom build, I noticed that I had to rebuild |
@scott-xu Are you involved with the extensions projects or do I need to request separately new builds when 3.3.5 comes out? |
3.3.5 should be compatible with the extensions |
@nschuessler Ninject 3.3.5 rc1 is released. Please give a try https://www.nuget.org/packages/Ninject/3.3.5-rc1 |
I ran a bunch of tests on the RC version outside of production. It seems to be fine. |
Given the simplified repro below, the following code throws
InvalidProgramException
on the delegate used to create theeventId
parameter (marked). This works with .Net 5.0.Any tips what to do here?
The code:
The text was updated successfully, but these errors were encountered: