Skip to content

Commit f5e8b38

Browse files
Merge pull request #1068 from icsharpcode/issue/786
Cast to dynamic when the accessed member can't be found but the surro…
2 parents 14c7d34 + 60bee52 commit f5e8b38

3 files changed

Lines changed: 47 additions & 5 deletions

File tree

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ public override async Task<CSharpSyntaxNode> VisitMemberAccessExpression(VBasic.
420420
}
421421
if (left == null) {
422422
left = await node.Expression.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor);
423+
if (left != null && _semanticModel.GetSymbolInfo(node) is {CandidateReason: CandidateReason.LateBound, CandidateSymbols.Length: 0}
424+
&& _semanticModel.GetSymbolInfo(node.Expression).Symbol is {Kind: var expressionSymbolKind}
425+
&& expressionSymbolKind != SymbolKind.ErrorType
426+
&& _semanticModel.GetOperation(node) is IDynamicMemberReferenceOperation) {
427+
left = SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName("dynamic"), left));
428+
}
423429
}
424430
if (left == null) {
425431
if (IsSubPartOfConditionalAccess(node)) {

Tests/CSharp/ExpressionTests/ExpressionTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,43 @@ private void TestMethod(string a)
4343
}");
4444
}
4545

46+
[Fact]
47+
public async Task DynamicTestAsync()
48+
{
49+
await TestConversionVisualBasicToCSharpAsync(@"
50+
Public Class C
51+
Public Function IsPointWithinBoundaryBox(ByVal dblLat As Double, dblLon As Double, ByVal boundbox As Object) As Boolean
52+
If boundbox IsNot Nothing Then
53+
Dim boolInLatBounds As Boolean = (dblLat <= boundbox.north) And (dblLat >= boundbox.south) 'Less then highest (northmost) lat, AND more than lowest (southmost) lat
54+
Dim boolInLonBounds As Boolean = (dblLon >= boundbox.west) And (dblLon <= boundbox.east) 'More than lowest (westmost) lat, AND less than highest (eastmost) lon
55+
Return boolInLatBounds And boolInLonBounds
56+
Else
57+
'Throw New Exception(""boundbox is null."")
58+
End If
59+
Return False
60+
End Function
61+
End Class
62+
", @"using Microsoft.VisualBasic.CompilerServices; // Install-Package Microsoft.VisualBasic
63+
64+
public partial class C
65+
{
66+
public bool IsPointWithinBoundaryBox(double dblLat, double dblLon, object boundbox)
67+
{
68+
if (boundbox is not null)
69+
{
70+
bool boolInLatBounds = Conversions.ToBoolean(Operators.AndObject(Operators.ConditionalCompareObjectLessEqual(dblLat, ((dynamic)boundbox).north, false), Operators.ConditionalCompareObjectGreaterEqual(dblLat, ((dynamic)boundbox).south, false))); // Less then highest (northmost) lat, AND more than lowest (southmost) lat
71+
bool boolInLonBounds = Conversions.ToBoolean(Operators.AndObject(Operators.ConditionalCompareObjectGreaterEqual(dblLon, ((dynamic)boundbox).west, false), Operators.ConditionalCompareObjectLessEqual(dblLon, ((dynamic)boundbox).east, false))); // More than lowest (westmost) lat, AND less than highest (eastmost) lon
72+
return boolInLatBounds & boolInLonBounds;
73+
}
74+
else
75+
{
76+
// Throw New Exception(""boundbox is null."")
77+
}
78+
return false;
79+
}
80+
}");
81+
}
82+
4683
[Fact]
4784
public async Task ConversionOfNotUsesParensIfNeededAsync()
4885
{

Tests/CSharp/StandaloneStatementTests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,12 @@ End If
135135
var cmccIds = new List<int>();
136136
foreach (var scr in _sponsorPayment.SponsorClaimRevisions)
137137
{
138-
foreach (var claim in (IEnumerable)scr.Claims)
138+
foreach (var claim in (IEnumerable)((dynamic)scr).Claims)
139139
{
140-
if (claim.ClaimSummary is ClaimSummary)
140+
if (((dynamic)claim).ClaimSummary is ClaimSummary)
141141
{
142142
{
143-
var withBlock = (ClaimSummary)claim.ClaimSummary;
143+
var withBlock = (ClaimSummary)((dynamic)claim).ClaimSummary;
144144
cmccIds.AddRange(withBlock.UnpaidClaimMealCountCalculationsIds);
145145
}
146146
}
@@ -151,9 +151,8 @@ End If
151151
2 source compilation errors:
152152
BC30451: '_sponsorPayment' is not declared. It may be inaccessible due to its protection level.
153153
BC30002: Type 'ClaimSummary' is not defined.
154-
3 target compilation errors:
154+
2 target compilation errors:
155155
CS0103: The name '_sponsorPayment' does not exist in the current context
156-
CS1061: 'object' does not contain a definition for 'ClaimSummary' and no accessible extension method 'ClaimSummary' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
157156
CS0246: The type or namespace name 'ClaimSummary' could not be found (are you missing a using directive or an assembly reference?)");
158157
}
159158
}

0 commit comments

Comments
 (0)