0

I'm working on a .NET Core 5 application. In some parts of the system, I'm using a cast to dynamic to handle generic type resolution. Something like this:

public void Foo(ISomething something){
    Bar((dynamic)something);
}

private void Bar<T>(T somethingElse) where T : ISomething
{ .... }

Works pretty well if I run the whole application. Now, for some mysterious reason, the same code refuses to work during Unit Tests. I get an exception as soon as it tries to call Bar<T>(), complaining that it's receiving an object instead of an ISomething. I'm using XUnit.

Any idea?

UPDATE 10/01/2021 I've pushed the code to GitHub, the branch is coverage.

This is the failing test. The issue happens on this line in the InMemoryPublisher class, when casting the message to dynamic.

David Guida
  • 950
  • 9
  • 19
  • You can’t use dynamic with generics like that. Generally speaking you should avoid using `dynamic` entirely. `dynamic` is its own *static-type* which does not implement interfaces. – Dai Jan 10 '21 at 02:48
  • Is there a reason you don’t just pass `something` directly into `Bar` without casting to `dynamic`? Also note that “resolution” is the wrong term: overloads are _resolved_, but generics are _instantiated_. – Dai Jan 10 '21 at 02:52
  • it works pretty well at runtime, as noted here: https://stackoverflow.com/a/35340243/3279163 – David Guida Jan 10 '21 at 02:54
  • I agree with you when it comes to avoiding `dynamic` as much as possible, but to be fair I don't think I have many choices here. Internally I have to call generic methods on other classes and I need the concrete type from `something`, not the interface. – David Guida Jan 10 '21 at 02:57
  • Does this not work ? `Foo(T something) where T : ISomething { Bar(something) }` – TheGeneral Jan 10 '21 at 03:15
  • I cant change Foo, it has to take the interface as parameter. But the issue here is NOT with the design. I want to understand why this thing works normally and fails only during tests – David Guida Jan 10 '21 at 03:27
  • You will need a [mcve] of both it working and it not working. – TheGeneral Jan 10 '21 at 04:29
  • Are your tests running under .NET 5 - or .NET Core 1,2,3, or even .NET Framework? .NET 5 introduced some major changes to the CLR and you may have stumbled across an undocumented breaking-change. As the others have said **we need a minimum reproducible example** - do you have a git repo I can clone? – Dai Jan 10 '21 at 04:37
  • Sure. I'll push everything tomorrow and let you know. It's .NET 5, btw. Thanks! – David Guida Jan 10 '21 at 05:16
  • I've updated the question and added more details. Thanks! – David Guida Jan 10 '21 at 17:18

1 Answers1

0

ok, I found the issue. I had marked the ISomething implementations as internal. Switching to public fixed it.

David Guida
  • 950
  • 9
  • 19