Skip to content

Fix: WithUseInterpretation() still triggers DynamicMethod on Xamarin.iOS AOT (SIGABRT) - #699

Draft
dadhi with Copilot wants to merge 6 commits into
masterfrom
copilot/fix-dryioc-resolve-issue
Draft

Fix: WithUseInterpretation() still triggers DynamicMethod on Xamarin.iOS AOT (SIGABRT)#699
dadhi with Copilot wants to merge 6 commits into
masterfrom
copilot/fix-dryioc-resolve-issue

Conversation

Copilot AI commented Apr 8, 2026

Copy link
Copy Markdown

When Rules.WithUseInterpretation() is configured (intended for AOT platforms like Xamarin.iOS), DryIoc could still internally call Expression.Compile(preferInterpretation: true) as a fallback when the DryIoc interpreter failed for an expression. On Mono/AOT, this internally creates a DynamicMethod, causing PlatformNotSupportedException / SIGABRT — typically observed on second navigation in Xamarin.Forms apps.

Changes

  • FactoryDelegateCompiler.CompileOrInterpretFactoryDelegate: When preferInterpretation = true, instead of falling back to Expression.Compile(), return a delegate that wraps the DryIoc interpreter directly. This eliminates all DynamicMethod / IL emit paths when UseInterpretation = true.

  • Error.UnableToInterpretExpression: New error code with an actionable message thrown when the interpreter cannot handle an expression (e.g., ExpressionFactory with complex arbitrary expressions like Conditional that are not covered by the DryIoc interpreter). Previously this silently fell back to compilation, which is the wrong behavior on AOT platforms.

// Before: when interpreter failed, fell back to Expression.Compile() → DynamicMethod on Mono/AOT
return new FactoryDelegateExpression(expression).ToLambdaExpression()
    .Compile(preferInterpretation); // ← SIGABRT on Xamarin.iOS AOT

// After: wrap interpreter in a delegate; throw clear ContainerException if expression is uninterpretable
return r => Interpreter.TryInterpretAndUnwrapContainerException(r, expression, out var result)
    ? result
    : Throw.For<object>(Error.UnableToInterpretExpression, expression);
  • GHIssue571 tests: Added tests covering:
    • Multiple scope open/close cycles (simulating repeated page navigation) to validate interpretation works correctly across scopes without triggering compilation.
    • Test_UnableToInterpretExpression_thrown_for_unsupported_expression_with_UseInterpretation: verifies that when an ExpressionFactory produces a Conditional expression (not handled by the DryIoc interpreter), a ContainerException(Error.UnableToInterpretExpression) is thrown instead of falling back to Expression.Compile() / DynamicMethod.

Behavioral note: On JIT platforms (Android, .NET Core), CompileOrInterpretFactoryDelegate(false) is unchanged — FEC + Expression.Compile() are still used when UseInterpretation = false. The only affected code path is the preferInterpretation = true branch.

Copilot AI changed the title [WIP] Fix DryIocTypeResolver.Resolve SIGABRT on iOS release configuration Fix: WithUseInterpretation() still triggers DynamicMethod on Xamarin.iOS AOT (SIGABRT) Apr 9, 2026
Copilot finished work on behalf of dadhi April 9, 2026 00:26
Copilot AI requested a review from dadhi April 9, 2026 00:26
Comment thread src/DryIoc/Container.cs Outdated
// Instead, return a delegate that wraps the DryIoc interpreter so that no code is compiled or emitted at runtime.
// If the expression cannot be interpreted (e.g., it uses Made.Of with complex arbitrary expressions
// not covered by the DryIoc Interpreter), a ContainerException with a helpful message is thrown.
var capturedExpr = expression;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why capturedExpr, why not use expression directly?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed in 2aeaf03 - expression is already a local variable (reassigned from NormalizeExpression()) so capturing it directly works fine.

Comment thread src/DryIoc/Container.cs
ServiceTypeIsNull = Of("Registered service type is null"),
RegisterAttributedUnsupportedReuseType = Of("Not support reuse type {0} in the RegisterAttribute.");
RegisterAttributedUnsupportedReuseType = Of("Not support reuse type {0} in the RegisterAttribute."),
UnableToInterpretExpression = Of(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Add the test which actually goes to this condition branch and throws this expression, with the complex Made.Of or someth not supported by DryIoc interpreter.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added Test_UnableToInterpretExpression_thrown_for_unsupported_expression_with_UseInterpretation in 2aeaf03. It uses ExpressionFactory with a Conditional (ternary) expression — ExprType.Conditional is not in the interpreter's TryInterpret switch, so it hits default: return false. With UseInterpretation=true, the fix throws ContainerException(Error.UnableToInterpretExpression) instead of falling back to Expression.Compile().

…pression with unsupported expression

Agent-Logs-Url: https://github.com/dadhi/DryIoc/sessions/ee4d901f-a04e-4144-a30a-ab1c31e16e78

Co-authored-by: dadhi <39516+dadhi@users.noreply.github.com>
Copilot AI requested a review from dadhi April 9, 2026 06:38
Copilot finished work on behalf of dadhi April 9, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Xamarin.iOS] DryIocTypeResolver.Resolve (System.Type type) SIGABRT: Operation is not supported on this platform.

2 participants