When I run the following code I get RuntimeBinderException: 'object' does not contain a definition for 'SetIt'.
public interface IInput { }
public interface IThing<in TInput>
{
void SetIt(TInput value);
}
public class ThingMaker
{
private class Thing<TInput> : IThing<TInput>
where TInput : IInput
{
public void SetIt(TInput value){}
}
private class Input : IInput {}
public IThing<IInput> GetThing()
{
return new Thing<IInput>();
}
public IInput GetInput()
{
return new Input();
}
}
class Program
{
static void Main(string[] args)
{
var thingMaker = new ThingMaker();
var input = thingMaker.GetInput();
dynamic thing= thingMaker.GetThing();
thing.SetIt(input);
}
}
If I switch thing to a var it works fine. So clearly, thing has SetIt. How come this fails when I use dynamic? Shouldn't any thing that works as var also work when it is dynamic?
I think it has something to do with Thing<TInput> being a private inner class because it works when I make it public.
Here is a simpler example of your problem:
class A
{
class B
{
public void M() { }
}
public static object GetB() { return new B(); }
}
class Program
{
static void Main(string[] args)
{
dynamic o = A.GetB();
o.M();
}
}
The generics and interfaces are just a distraction.
The problem is that the type B (or in your case, Thing<IInput>) is a private class, and so at the call site, cannot resolve to that actual type. Recall that dynamic simply is an object variable but where compilation has been postponed until run-time. It isn't intended to let you do things at run-time you wouldn't otherwise be able to do, and "wouldn't otherwise be able to do" is judged based on the accessible type at the call site (which in this case, is object).
As far as the runtime binder is concerned, the type is simply object (hence the error message telling you that object doesn't contain the member you want).
Of course, it is theoretically possible that dynamic could have been implemented differently, and could do a more in-depth search for valid types it could treat the object as for the purpose of binding members to the object (i.e. implemented interfaces rather than just the object's actual type). But that's just not how it was implemented, and it would have been much more costly to do so (both in terms of the original design and implementation, and of course in terms of run-time cost of code that uses dynamic).
Related reading (arguably duplicates):
Is this a bug in dynamic?
Is this a hole in dynamic binding in C# 4?
Related
I tried to use dynamic to access methods of classes that are located in another assembly. These classes are internal and created by builders that return a public interface. For some reason dynamic is not able to invoke the method defined on the interface. I can use "classic" reflection to get the code running but I don't understand why it's not working with dynamic.
I know that dynamic is not working with methods of internal classes but here we have a public interface. So please can someone explain why dynamic throws the RuntimeBinderException in the example below?
namespace SandboxLib // located in SandboxLib.dll
{
public class InternalBuilder
{
public static IInterface Build()
{
return new InternalClass();
}
}
public interface IInterface
{
void IfMethod();
}
internal class InternalClass : IInterface
{
public void IfMethod() { }
}
}
namespace Sandbox // located in Sandbox.dll
{
public class Program
{
static void Main(string[] args)
{
var inst = InternalBuilder.Build();
dynamic dynInst = inst;
inst.IfMethod(); // ok
dynInst.IfMethod(); // Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'IfMethod'
}
}
}
This behaviour is described in the C# Standard:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#dynamic-binding
Under "Member Lookup" it states:
Member lookup considers not only the name of a member but also the
number of type parameters the member has and whether the member is
accessible.
Since the member IfMethod() that the dynamic resolution has found is internal, the call will fail, as per the specification.
Why does this program output Generic Value and not Hello world!:
using System;
class Example
{
public static void Print<T>(T value)
{
Console.WriteLine("Generic Value");
}
public static void Print(string value)
{
Console.WriteLine(value);
}
public static void GenericFunc<T>(T value)
{
Print(value);
}
static void Main()
{
GenericFunc("Hello world!");
}
}
How is the generic method parameter being translated under the hood of C#?
Overload resolution is only done at compile-time.
Since GenericFunc<T> doesn't know whether T is a string or something else at compile-time, it can only ever use the Print<T>(T value) "overload".
Using dynamic, you can change this to a dynamic dispatch, and get the behaviour you expect:
Print((dynamic)value);
This makes the overload resolution happen at runtime, with the actual runtime type of value.
Simple answer to simple question
The other answer explains the way generic are bound (compile-time). But it doesn't answer on the OOP, good practice, or simply why you should never write this code in the first place.
OOP
The first O in OOP means Object and there is none with only static methods.
Responsibility
Let's think about the Generic versin of the method as a method responsible for printing a set of different possible types. String type is part of the set. So it should be managed by the generic version of your Print function.
public static void Print<T>(T value)
{
Console.WriteLine(value.ToString());
}
then you got the problem of nullity for ref types.
public static void Print<T>(T value) where T : class
{
if (value != null)
{
Console.WriteLine(value.ToString());
}
}
public static void GenericFunc<T>(T value) where T : class
{
Print(value);
}
And for those who are aware of why you should not use dynamic unless in some cases (see my anwer on that).
More clean OOP solution
Now imagine you have different objects to print. Each object should be responsible for knowing how to display it. Firstly, because it ease encapsulation of data by not leaking internal data to the external world. Secondly, because you've got an inherent coupling between the internal data and the printing function, so both should be located in the same place: inside the class. That's the purpose of the ToString function.
Let's take some height...
Now, we could imagine that it's not a Print function but something else.
We got a hierarchy of classes with overload on the same function (let's call it Foo) and a collection of instances from these classes for which you must call the function Foo. Let's then make all these classes implement the IFooCallable interface :
public interface IFooCallable
{
void Foo();
}
A little more complex...
Ok, but imagine that there is not common way to process all these instances of classes because there are very different.
Let's call the Visitor pattern. It's commonly used when you want to analyze some object tree with each node very different (like in AST).
It's a known pattern, making it easy to share knowledgable information with your team.
You got the Visitor:
public class Visitor : IVisitor
{
public void Visit(Foo foo)
{
// do something with foo
}
public void Visit(Bar bar)
{
// do something with bar
}
}
and the Visitable
public class Foo : IVisitable
{
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
Moreover this pattern is reusable (you could write several implementation of IVisitor should you need to).
I don't buy the dynamic thing. Especially when there is more cleaner, faster alternative. If dynamic so great, why not writing this then ;)
public static void Print(dynamic value)
{
Console.WriteLine(value);
}
public static void GenericFunc(dynamic value)
{
Print(value);
}
static void Main(dynamic[] args)
{
GenericFunc((dynamic)"Hello World");
}
I'm experimenting with explicit implentations of interfaces. This is to strip the intellisense with methods which are not valid in the current context.
Use /practical-applications-of-the-adaptive-interface-pattern-the-fluent-builder-context/ as reference. To prove that they would not be callable, I thought I could use the dynamic keyword, because then at least my code would compile. It does compile, but it does not work as expected. The dynamic variable has access to the class methods, but not the interface methods that are explicit implemented.
public interface IAmInterface
{
void Explicit();
void Implicit();
}
public class Implementation : IAmInterface
{
void IAmInterface.Explicit()
{
}
public void Implicit()
{
}
public static Implementation BeginBuild()
{
return new Implementation();
}
}
And here are the 3 tests to prove my point
[Test]
public void TestWorksAsExpected() //Pass
{
var o = Implementation.BeginBuild();
o.Implicit();
}
[Test]
public void TestDoesNotWorkWithExplicitImplementation() //Fails
{
dynamic o = Implementation.BeginBuild();
o.Explicit();
}
[Test]
public void ButWorksForImplicitImplementation() //Pass
{
dynamic o = Implementation.BeginBuild();
o.Implicit();
}
Would anyone be kind enough to explain the reason for this?
One example where I wanted this functionality was to prove that I couldnt add more than two players in a TennisGame.
dynamic o = TennisGame.BeginBuild().With("Player A").Versus("Player B");
o.Versus("Player C"); //Should fail. It does, but for another reason
The dynamic variable has access to the class methods, but not the interface methods that are explicit implemented.
Yes, that is correct. dynamic has access to the regular members that would be accessible (based on context etc, usually means "public"). However, the only way, even in regular C#, to invoke explicit interface implementations, is to cast the object to the interface. This remains the case with dynamic.
Implicit interfact implementations are also part of the regular class API, so they are externally available (against the type) to both regular c# and dynamic.
Basically: no, dynamic can not and will not access explicit interface implementations.
Either cast to the interface, or use reflection from the interface type (not the object type).
Is it possible to reflect on an explicit interface implementation from the call stack? I want to use this info to look up an attribute on the interface itself.
Given this code:
interface IFoo
{
void Test();
}
class Foo : IFoo
{
void IFoo.Test() { Program.Trace(); }
}
class Program
{
static void Main(string[] args)
{
IFoo f = new Foo();
f.Test();
}
public static void Trace()
{
var method = new StackTrace(1, false).GetFrame(0).GetMethod();
// method.???
}
}
Specifically, in Trace(), I would like to be able to get to typeof(IFoo) from method.
In the watch window, if I look at method.ToString() it gives me Void InterfaceReflection.IFoo.Test() (InterfaceReflection is the name of my assembly).
How can I get to typeof(IFoo) from there? Must I use a name-based type lookup from the assembly itself, or is there a Type IFoo hidden somewhere in the MethodBase?
UPDATE:
Here's the final solution, thanks to Kyte
public static void Trace()
{
var method = new StackTrace(1, false).GetFrame(0).GetMethod();
var parts = method.Name.Split('.');
var iname = parts[parts.Length - 2];
var itype = method.DeclaringType.GetInterface(iname);
}
itype will have the interface type for the implementing method. This will only work with explicit interface implementations, but that's exactly what I need. Now I can use itype to query attributes attached to the actual interface type.
Thanks to everyone for their help.
Testing around with VS2010, I found DeclaringType, which gets the object type that contains the method, from where you can get the interfaces as Type objects.
public static void Trace() {
var stack = new StackTrace(1, true);
var frame = stack.GetFrame(0);
var method = frame.GetMethod();
var type = method.DeclaringType;
Console.WriteLine(type);
foreach (var i in type.GetInterfaces()) {
Console.WriteLine(i);
}
}
Returns:
TestConsole.Foo
TestConsole.IFoo
(I called the project TestConsole)
method will be a System.Reflection.RuntimeMethodInfo, which is a class derived from System.Reflect.MethodBase. You could e.g. call Invoke() on it (though if you did so at the point where you obtained it, then this is going to result in an infinite recursion that eventually dies by overflowing the stack).
Calling ToString() on it returns a fully qualified name. Did you call the project InterfaceReflection?
Not sure what more you want than that.
Edit: Okay, now I do. To find the declaring type look at the DeclaringType property, this will return the class on which the method was declared (which could be the class it was called on, or a base class):
So far so easy, this returns a Type object for Foo.
Now for the tricky bit, because you care about the interface it was declared on. However, there could be more than one interface that defined a method with precisely the same signature, which means the simple question "if this came from an interface, what was that interface?" doesn't always have a single answer.
There may be a neater way to do this, but all I can think of is calling GetInterfaces() on the Type object you got from DeclaringType, and then looking for one whose name matches the method's signature.
I don't want to presume too much, but in this case, it looks like you may be causing some confusion because Foo and Program are inter-dependent. Typically, I would think Program would "own" Foo (which would be agnostic of Program) in such a way that it's responsible for setting the delegate so reflection could likely be avoided...the way you have it set up, Foo "owns" (actually, I guess depends on is probably more accurate) Program in a way (because it's hardcoing a a call to its Program.Trace() ), and Program "owns" Foo in a way (because it controls the instance).
I don't know if this would work in your particular scenerio, but it looks like an event type operation might make more sense and handle the communication more simply.
ETA: Code sample:
public interface IFoo
{
event EventHandler Testing;
void Test();
}
public class Foo : IFoo
{
public event EventHandler Testing;
protected void OnTesting(EventArgs e)
{
if (Testing != null)
Testing(this, e);
}
public void Test()
{
OnTesting(EventArgs.Empty);
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
IFoo f = new Foo();
f.Testing += new EventHandler(f_Testing);
f.Test();
}
static void f_Testing(object sender, EventArgs e)
{
IFoo foo = sender as IFoo;
if (foo != null)
{
//...
}
}
}
I might be misunderstanding your question, though.
I think .NET appends the full name to the front of the MethodInfo.Name property so that it has a unique name for each method. Think of:
interface IFoo
{
void Test();
}
interface IFoo2
{
void Test();
}
class Foo : IFoo, IFoo2
{
void IFoo.Test() { Trace(); }
void IFoo2.Test() { Trace(); }
}
In this case, typeof(Foo).GetMethods() would return both Test() methods but their names would conflict, so I guess they appended the interface name to make them unique?
The MethodInfo.DeclaringType returns the type that contains the implementation. So if IFoo were actually some base type instead of an interface, and there was a base method declaration there, then .DeclaringType would return the type of the base class.
Interestingly, I can't seem to find the actual interface name anywhere in the MethodInfo either, so I guess you would have to look it up by name, something like:
public static void Trace()
{
var method = new System.Diagnostics.StackTrace(1, false).GetFrame(0).GetMethod();
var fromType = method.DeclaringType;
if (method.Name.Contains("."))
{
var iname = method.Name.Substring(0, method.Name.LastIndexOf('.'));
fromType = Type.GetType(iname); // fromType is now IFoo.
}
}
In a non-static method I could use this.GetType() and it would return the Type. How can I get the same Type in a static method? Of course, I can't just write typeof(ThisTypeName) because ThisTypeName is known only in runtime. Thanks!
If you're looking for a 1 liner that is equivalent to this.GetType() for static methods, try the following.
Type t = MethodBase.GetCurrentMethod().DeclaringType
Although this is likely much more expensive than just using typeof(TheTypeName).
There's something that the other answers haven't quite clarified, and which is relevant to your idea of the type only being available at execution time.
If you use a derived type to execute a static member, the real type name is omitted in the binary. So for example, compile this code:
UnicodeEncoding.GetEncoding(0);
Now use ildasm on it... you'll see that the call is emitted like this:
IL_0002: call class [mscorlib]System.Text.Encoding
[mscorlib]System.Text.Encoding::GetEncoding(int32)
The compiler has resolved the call to Encoding.GetEncoding - there's no trace of UnicodeEncoding left. That makes your idea of "the current type" nonsensical, I'm afraid.
Another solution is to use a selfreferecing type
//My base class
//I add a type to my base class use that in the
//static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
public static Type GetType()
{
return typeof(TSelfReferenceType);
}
}
Then in the class that inherits it, I make a self referencing type:
public class Child: Parent<Child>
{
}
Now the call type typeof(TSelfReferenceType) inside Parent will get and return the Type of the caller without the need of an instance.
Child.GetType();
You can't use this in a static method, so that's not possible directly. However, if you need the type of some object, just call GetType on it and make the this instance a parameter that you have to pass, e.g.:
public class Car {
public static void Drive(Car c) {
Console.WriteLine("Driving a {0}", c.GetType());
}
}
This seems like a poor design, though. Are you sure that you really need to get the type of the instance itself inside of its own static method? That seems a little bizarre. Why not just use an instance method?
public class Car {
public void Drive() { // Remove parameter; doesn't need to be static.
Console.WriteLine("Driving a {0}", this.GetType());
}
}
I don't understand why you cannot use typeof(ThisTypeName). If this is a non-generic type, then this should work:
class Foo {
static void Method1 () {
Type t = typeof (Foo); // Can just hard code this
}
}
If it's a generic type, then:
class Foo<T> {
static void Method1 () {
Type t = typeof (Foo<T>);
}
}
Am I missing something obvious here?
When your member is static, you will always know what type it is part of at runtime. In this case:
class A
{
public static int GetInt(){}
}
class B : A {}
You cannot call (edit: apparently, you can, see comment below, but you would still be calling into A):
B.GetInt();
because the member is static, it does not play part in inheritance scenarios. Ergo, you always know that the type is A.
For my purposes, I like #T-moty's idea. Even though I have used "self-referencing type" information for years, referencing the base class is harder to do later.
For example (using #Rob Leclerc example from above):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Working with this pattern can be challenging, for example; how do you return the base class from a function call?
public Parent<???> GetParent() {}
Or when type casting?
var c = (Parent<???>) GetSomeParent();
So, I try to avoid it when I can, and use it when I must. If you must, I would suggest that you follow this pattern:
class BaseClass
{
// All non-derived class methods goes here...
// For example:
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
// All derived class methods goes here...
// For example:
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
Now you can (more) easily work with the BaseClass. However, there are times, like my current situation, where exposing the derived class, from within the base class, isn't needed and using #M-moty's suggestion just might be the right approach.
However, using #M-moty's code only works as long as the base class doesn't contain any instance constructors in the call stack. Unfortunately my base classes do use instance constructors.
Therefore, here's my extension method that take into account base class 'instance' constructors:
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor.
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
// Skip all the base class 'instance' ctor calls.
//
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}
EDIT
This methods will works only when you deploy PDB files with the executable/library, as markmnl pointed out to me.
Otherwise will be a huge issue to be detected: works well in developement, but maybe not in production.
Utility method, simply call the method when you need, from every place of your code:
public static Type GetType()
{
var stack = new System.Diagnostics.StackTrace();
if (stack.FrameCount < 2)
return null;
return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType;
}