Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static method requires null instance, non-static method requires non-null instance. #542

Closed
GF-Huang opened this issue Feb 17, 2022 · 7 comments
Assignees
Labels
area:web-api Issue with WebApiModule and/or related classes. bug closed-as:not-a-bug The issue was closed because it is not a bug. v3.x

Comments

@GF-Huang
Copy link

I use Stylet as MVVM framework, it contains a IoC component for DI.

Screenshots
This work:

image

This not work:

image

Desktop (please complete the following information):

  • OS: Win10 21H2
  • Browser MSEDGE
  • Version 3.4.3

Additional context
Add any other context about the problem here.

@rdeago rdeago added area:web-api Issue with WebApiModule and/or related classes. bug v3.x labels Feb 18, 2022
@rdeago
Copy link
Collaborator

rdeago commented Feb 18, 2022

Hello @GF-Huang, thanks for using EmbedIO!

While this could be a bug in WebApiModuleBase, I have not been able to reproduce it.

Can you post the exception's stack trace? It will probably help determine the exact cause of the issue.

@GF-Huang
Copy link
Author

image

image

@GF-Huang
Copy link
Author

BTW, does EmbedIO supports model validation in post method while body is json?

@rdeago
Copy link
Collaborator

rdeago commented Mar 9, 2022

Hello @GF-Huang, sorry for the late answer.

EmbedIO does no model validation as of now. It will probably be easier to add it in version 4, because the deserialization APIs will be more open. For more details, keep an eye on #546.

As for the original issue, I think it may have to do with the actual value of _apiControllerFactory. Are you passing a static or instance method to ApiService's constructor?

@GF-Huang
Copy link
Author

GF-Huang commented Mar 9, 2022

As for the original issue, I think it may have to do with the actual value of _apiControllerFactory. Are you passing a static or instance method to ApiService's constructor?

I'm not sure, but this depends on Stylet implementation, and this is its docs about Func<T> factory.

@rdeago rdeago self-assigned this Mar 9, 2022
@rdeago rdeago added the closed-as:not-a-bug The issue was closed because it is not a bug. label Mar 9, 2022
@rdeago
Copy link
Collaborator

rdeago commented Mar 9, 2022

@GF-Huang thanks for the link. I've had a look at both the docs and StyletIoC's source code.

If I understand correctly, you register ApiController as an injectable type, then your constructor needs a Func<ApiController>, so StyletIoC automnatically generates a factory function for you.

How it generates the factory function is the interesting part IMHO: it uses types in the System.Reflection.Emit namespace to generate IL code directly; it's almost as if a C++ function wrote a machine code function in a memory buffer and returned a pointer to the buffer. 😱

There are actually no "functions" in .NET, only methods. A method, as you know, may be static or non-static; a non-static method requires a "this" reference at runtime. Every method has some associated metadata, among which there's an "IsStatic" flag that tells whether the method needs a "this" reference (IsStatic = 0) or not (ISStatic = 1).

When you generate methods using System.Reflection.Emit, you can do pretty much anything, including screwing up badly. 😁 For instance, you can generate an instance of a delegate that points to a non-static method but with a null "this". I suspect this is what happens here.

When WebModuleBase uses the delegate instance in a LINQ expression, System.Linq.Expression checks the congruence between the method's metadata and the "this" reference contained in the delegate instance, finds IsStatic=0 and this=null, and throws an exception.

In other words, this is most probably a bug in Stylet. The delegate usually works because, despite it being non-static, never references "this" in code.

Your workaround (enclosing a call to the delegate in a lambda, () => _apiControllerFactory()) is correct. The contents of the delegate instance are unknown at compile time and the compiled lambda does no congruence check at run time, so the delegate is called and, since it doesn't use "this", it runs without problems.

Closing this issue since it doesn't seem to be a bug in EmbedIO after all. Feel free to reopen if further examination proves me wrong (which is totally possible, as I'm no expert when it comes to IL code and System.Reflection.Emit).

@rdeago rdeago closed this as completed Mar 9, 2022
@GF-Huang
Copy link
Author

GF-Huang commented Mar 9, 2022

Got it, and thanks your detailed analysis. 🌹

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:web-api Issue with WebApiModule and/or related classes. bug closed-as:not-a-bug The issue was closed because it is not a bug. v3.x
Projects
None yet
Development

No branches or pull requests

2 participants