Closed GF-Huang closed 2 years ago
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.
BTW, does EmbedIO
supports model validation in post method while body is json?
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?
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 toApiService
's constructor?
I'm not sure, but this depends on Stylet
implementation, and this is its docs about Func<T>
factory.
@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
).
Got it, and thanks your detailed analysis. 🌹
I use Stylet as MVVM framework, it contains a IoC component for DI.
Screenshots This work:
This not work:
Desktop (please complete the following information):
Additional context Add any other context about the problem here.