In the rare case that two types have exactly the same type name, dynamic operations will fail:
C#
dynamic x = Activator.CreateInstance(
AssemblyBuilder
.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("TestModule")
.DefineType("TestType", TypeAttributes.Public)
.CreateType());
dynamic y = Activator.CreateInstance(
AssemblyBuilder
.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("TestModule")
.DefineType("TestType", TypeAttributes.Public)
.CreateType());
x.Equals(y); // This or any other operation with both objects fails.
dotnet/corefx#23021 changed the exception thrown in this case from RuntimeBinderInternalCompilerException to RuntimeBinderException; pretty much a change from "sorry, we got this wrong" to "sorry, you can't do that".
Ideally such cases should succeed. While the case is extremely rare:
While the first two points relate to what is an obscure edge case, the third is a greater motivation for allowing this IMO.
CC: @VSadov @OmarTawfik
@JonHanna Is there a way to workaround the issue in a 4.6.2 project?
Maybe I can install Microsoft.Csharp from nuget?
@molinch maybe work from nightlies? I know less about the various packaging versions than I really should, so someone else would give a better answer (@karelz ?)
The best I can think of is to use explicit reflection instead of dynamic.
Basically in my case I am using Roslyn scripting API, and provide some dynamic into the globals object passed to scripting API.
c#
public class FormulaGlobals
{
public dynamic g;
}
I have a couple of scripts, and they assign different values to g (which is in fact a Dictionaryg["SOMETHING"]
But at some point I get this ResetBindException. I'm pretty sure your commit would fix it.
I guess there is no way to clear the DLR cache?
@molinch. You should never see the ResetBindException as it should never escape MS.CSharp. Generally it should, as the name suggests, reset its global state and try again and only if it happens again in the second attempt — which would mean there were two different but identically-named types in the same operation — it should throw RuntimeBinderInternalCompilerException (or for a brief period with .NET Core, RuntimeBinderException). If ResetBindException is escaping into the calling code there's something else wrong.
Packaging is sill a bit of black magic for me as well :( (way too complicated with too many exceptions)
In general / high-level, we do not release standalone NuGet packages for all CoreFX-produced packages for all platforms -- Microsoft.CSharp seems to be in that category (from looking at its latest nuget package).
If there is a workaround, use it. If it is critical bug without reasonable workaround affecting non-trivial number of applications/customers, we may consider alternatives ...
Thanks a lot @JonHanna with your explanation it's much more clear. In fact my debugger was always breaking on this ResetBindException, so I thought it was a real issue, but you are right: it is handled internally and then the evaluation works. I guess working too late is never a good idea: you then find issues which aren't.
@karelz thanks for the time to answer me.
Most helpful comment
Thanks a lot @JonHanna with your explanation it's much more clear. In fact my debugger was always breaking on this ResetBindException, so I thought it was a real issue, but you are right: it is handled internally and then the evaluation works. I guess working too late is never a good idea: you then find issues which aren't.
@karelz thanks for the time to answer me.