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

Support collectible assemblies via new CollectibleProxyBuilder #685

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

stakx
Copy link
Member

@stakx stakx commented Aug 31, 2024

This is an alternative to #679. Consider it a proof of concept that is to be discussed further, over in #473. If we went ahead with this approach, the code here might have to be cleaned up a little more.

@stakx stakx marked this pull request as draft August 31, 2024 14:04
@stakx stakx force-pushed the enhancements/collectible-assemblies branch from 617627e to 42dfbc7 Compare October 19, 2024 18:32
@stakx stakx changed the title Draft: Support collectible assemblies via a new CollectibleProxyBuilder Support collectible assemblies via new CollectibleProxyBuilder Oct 19, 2024
@stakx stakx marked this pull request as ready for review October 19, 2024 18:33
@stakx stakx self-assigned this Oct 19, 2024
@stakx stakx added this to the vNext milestone Oct 19, 2024
@stakx
Copy link
Member Author

stakx commented Oct 19, 2024

@castleproject/committers, I'll let this PR sit for a few days, in case anyone wants to review. If there are no objections, I'll go ahead and merge it in a few days' time as the enhancement to DynamicProxy it contains is fairly trivial.

Copy link
Member

@jonorossi jonorossi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stakx Looks good. Could we add a very basic unit test to ensure the this new proxy builder at least works?

@stakx
Copy link
Member Author

stakx commented Nov 24, 2024

Thanks for reviewing.

You're right, I forgot to write a test, since this started out only as a proof of concept. I'll add one.

@simonferquel
Copy link

Hi @stakx, I have some reserve about this approach as it will require all moqing frameworks to opt-into leverage this to be able to work without leaking Assembly Load Contexts in environments that leverage them.

The example of Unity 7 where we are moving to CoreCLR and take advantage of ALCs (AssemblyLoadContext) to allow users to iterate on their code without reloading the editor:

  • We load user code and packages into an unloadable ALC. This user code may contain tests which uses any Moqing framework built on top of Castle.Core
  • Whenever the user modify its code or update a package, we cleanup all references the engine has to user object, and unload the user ALC, compile new version of code, and reload the new ALC

If any non-unloadable ALC keep references to anything loaded within the User ALC, the unload will never complete (the GC will see outstanding references to some objects belonging to that ALC and thus will keep it alive). We call that ALC leaks in Unity.

With that PR, if a Moqing framework relying on Castle.Core wants to play nice with Unity (or any other environment that does leverage unloadable ALCs), it will need to explicitly opt-into using this new CollectibleProxyBuilder. I don't think it is the responsibility of the Moqing framework, but more about the hosting process to decide in which kind of ALC generated code should get loaded: that is why I first introduced a global static setting that a runtime environment could use to define this behavior (e.g. if Unity detects that Castle.Core is loaded, it would set the setting accordingly so that any moqing framework would generate its code in a way that plays nice with Unity runtime).
The default setting value that would depend on whether Castle.Core itself is loaded in a Collectible ALC makes sense to me, as it means it as been loaded as a dependency of something that may be collected at some point in the process lifetime, and so whatever it generated dynamically should not be able to keep its ALC alive and should thus be collectible. But I could live with that logic not enabled.

So what I really think we should have to define if the builders should emit collectible types is this:

  • A global setting that could let an hosting environment set the safe defaults (with optionally the "sensible defaults" I introduced in the original PR relying on detecting if Castle.Core assembly itself is in a collectible ALC)
  • An explicit way to let direct users of Castle.Core override this global setting

That could be implemented by having:

  • DefaultProxyBuilder add a protected virtual bool GeneratedCollectibleTypes property, implemented by looking at the global setting
  • Adding a CollectibleProxyBuilder and NonCollectibleProxyBuilder that would override the property to ignore the global setting

What would you think of that ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants