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.
}
}
Related
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?
Currently I have something like this:
public abstract class Base {...}
public class Derived<T> : Base {...}
class Visitor {
public static void Visit<T>(Derived<T> d) {
...
}
}
My question is, given a Base reference that I know is a Derived instance, how can I apply that Visit function to that object, using the correct generic instantiation? I understand that the answer will probably involve a type-checked dynamic downcast, to make sure that the object isn't some other type derived from base, which is all fine. I assume the answer involves reflection, which is also fine, though I'd prefer if there was a way to do it without reflection.
It's also ok if the answer involves an abstract method on Base and Derived; I do have enough control of the classes to add that. But at the end of the day, I need to call a generic function, correctly instantiated with the T of the Derived type.
Sorry if this is an easy question; I come from a C++ background, where my instinct would be to use a CRTP or something else like that, which isn't possible in C#.
EDIT:
Here's an example of what I need to be able to do:
Base GetSomeDerivedInstance() { ...; return new Derived<...>(); }
var b = GetSomeDerivedInstance();
// This is the line that needs to work, though it doesn't necessarily
// need to have this exact call signature. The only requirement is that
// the instantiated generic is invoked correctly.
Visitor.Visit(b);
In my opinion, answers involving double-dispatch and More Classes are going to be superior than using reflection to do what inheritance should do for you.
Normally this means defining an 'accept' method on the visitable class, which simply calls the correct Visit method from the visitor.
class Base
{
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this); // This calls the Base overload.
}
}
class Derived<T> : Base
{
public override void Accept(Visitor visitor)
{
visitor.Visit(this); // this calls the Derived<T> overload.
}
}
public class Visitor
{
public void Visit(Base #base)
{
...
}
public void Visit<T>(Derived<T> derived)
{
...
}
}
Then you can do what you mentioned in your question, with a small modification:
Base b = createDerived();
b.Accept(new Visitor());
If your visit method is a static class that you can't change for whatever reason, you could always wrap this into a dummy instance visitor class which calls the right static method.
(Edited for clarity)
The following will use a variable called "anyvalue" whose type is only known at run-time. Then we'll create an instance of your Derived class based on the type of anyvalue. Once we have that instance, we can use reflection to get the correct Visit method.
var anyvalue = 5; // This value could have come from anywhere.
...
var derivedType = typeof (Derived<>).MakeGenericType(anyvalue.GetType());
var dvalue = Activator.CreateInstance(derivedType);
var method = typeof(Visitor).GetMethod("Visit");
var genericMethod = method.MakeGenericMethod(new[] { anyvalue.GetType() });
genericMethod.Invoke(null, new [] { dvalue });
What is a little confusing is that this is a skeletal example and you do not use the original value for anything other than getting a run-time type. In the real world implementation, I would assume a constructor would use that value to set internal state in the Derived instance. That is not covered here because that is not part of the question that was asked.
UPDATE:
I think this will do what you want. Note that I created the itemarray so that we would have some run-time values. They have to be created somewhere. So whether they are passed in as object[] or provided some other way, they had to be constructed with a type specifier somewhere. Also, this assumes that Derived<> is the only derived class. Otherwise, this is not safe code.
var itemarray = new Base[] { new Derived<int>(), new Derived<string>() };
foreach (var baseObject in itemarray)
{
var derivedType = baseObject.GetType();
var visitMethod = typeof(Visitor)
.GetMethod("Visit")
.MakeGenericMethod(derivedType.GetGenericArguments());
visitMethod.Invoke(null, new[] { baseObject });
}
The Accept approach does seem a bit more manageable. My goal was to answer the question you asked without passing judgment on your approach. I have needed to use this approach several times. I wrote an entity framework about 9 years ago. I had a really hard time doing exactly what you are trying to do. I created base classes that were not generic so that I could share basic functionality regardless of the generic type. It proved challenging. I am not sure I would do it the same way now. I'd probably investigate a few patterns just as you are doing.
You should be able to do something like the following:
Base foo = new Derived<int>();
var method = typeof(Visitor).GetMethod("Visit", BindingFlags.Public | BindingFlags.Static);
method.MakeGenericMethod(foo.GetType().GenericTypeArguments.First()).Invoke(null, new[] {foo});
Perhaps you're meaning something like this?
public class Derived<T>
{
}
public abstract class Derivable<T>
{
public Derived<T> CreateDerived()
{
return new Derived<T>();
}
}
public class Foo : Derivable<Foo>
{
}
class Visitor
{
public static void Visit<T>(Derived<T> obj)
{
Console.Out.WriteLine("Called!");
}
}
void Main()
{
var obj = new Foo();
var derived = obj.CreateDerived();
Visitor.Visit(derived);
}
If the creation of the Derived<T> is T-specific, then you'd make the CreateDerived method abstract and implement it for each T. Or use an IDerivable<T> interface instead if you don't want it as your base class.
How can I determine the underlying interface from which the method DoSomething() is called? Additional question: Can I already determine the underlying interface in the MyClass constructor? I assume not as it is not known at instantiation time, correct?
Edit: I am not looking for explicit interface implementations but a different way to determine the underlying interface.
public interface ITest
{
void DoSomething();
//....more methods
}
public interface IDecoy
{
void DoSomething();
//...more methods
}
public class MyClass : ITest, IDecoy
{
public void DoSomething()
{
//Question: How can I determine the underlying interface that called this method?
//at one time it is ITest, at another IDecoy. How can I figure out which one at each time?
}
}
public class Test
{
public Test()
{
ITest myClassInstance1 = new MyClass();
IDecoy myClassInstance2 = new MyClass();
myClassInstance1.DoSomething();
myClassInstance2.DoSomething();
}
}
public class MyClass : ITest, IDecoy
{
void ITest.DoSomething()
{
//called with ITest
}
void IDecoy.DoSomething()
{
//called with IDecoy
}
}
This question is quite intriguing, and so I set out to see whether it was possible to find a way of identifying which interface was used without the solution already suggested.
The solution I am using essentially finds the metadata token of the method that was called in the IL code of the caller and looks this up against the metadata token of the DoSomething method from each interface:
public void DoSomething()
{
StackFrame CallerFrame;
StackTrace CallStack;
int CodeOffset;
MethodBody MethodBody;
int MethodToken;
int TokenIDecoy;
int TokenITest;
// Get the metadata tokens for both interface methods
TokenIDecoy = Type.GetType("Proto.SO18203446.IDecoy").GetMethod("DoSomething").MetadataToken;
TokenITest = Type.GetType("Proto.SO18203446.ITest").GetMethod("DoSomething").MetadataToken;
// Get the caller
CallStack = new StackTrace();
CallerFrame = CallStack.GetFrame(1);
// Get the metadata token called by the IL
CodeOffset = CallerFrame.GetILOffset();
MethodBody = CallerFrame.GetMethod().GetMethodBody();
MethodToken = BitConverter.ToInt32(MethodBody.GetILAsByteArray(), CodeOffset - 4);
// Check to see which interface was used
if (MethodToken == TokenIDecoy)
Console.WriteLine("IDecoy was called");
else if (MethodToken == TokenITest)
Console.WriteLine("ITest was called");
else
Console.WriteLine("Not sure what happened here");
}
Remember to change the GetType call parameter to be your own namespace (so mine is Proto.SO18203446 but yours is very likely to be somehting else).
The steps of the process are simple:
Lookup the metadata tokens for each interface DoSomething method
Find the calling frame (the one that makes the call to DoSomething)
Lookup the IL offset of the call to the DoSomething method and extract the metadata token for it
Compare the called metadata token to the token for each DoSomething in the interfaces
I would like to add that I am not recommending or endorsing this code - it is more to prove that it is possible to achieve your aim from an academic perspective.
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;
}
I am looking for an algorithm that can get the object that called the method, within that method.
For instance:
public class Class1 {
public void Method () {
//the question
object a = ...;//the object that called the method (in this case object1)
//other instructions
}
}
public class Class2 {
public Class2 () {
Class1 myClass1 = new Class1();
myClass1.Method();
}
public static void Main () {
Class2 object1 = new Class2();
//...
}
}
Is there any way to do this?
Here's an example of how to do this...
...
using System.Diagnostics;
...
public class MyClass
{
/*...*/
//default level of two, will be 2 levels up from the GetCaller function.
private static string GetCaller(int level = 2)
{
var m = new StackTrace().GetFrame(level).GetMethod();
// .Name is the name only, .FullName includes the namespace
var className = m.DeclaringType.FullName;
//the method/function name you are looking for.
var methodName = m.Name;
//returns a composite of the namespace, class and method name.
return className + "->" + methodName;
}
public void DoSomething() {
//get the name of the class/method that called me.
var whoCalledMe = GetCaller();
//...
}
/*...*/
}
Posting this, because it took me a while to find what I was looking for myself. I'm using it in some static logger methods...
You could get to the current stack trace in code and walk up one step.
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
But as was commented below, this will get you the method and class calling you, but not the instance (if there is one, could be a static of course).
or just pass the object as method parameter.
public void Method(object callerObject)
{
..
}
and call the Method:
myClass.Method(this);
regards, Florian
It would be very bad style since
a) that would break encapsulation
b) it's impossible to know the type of the calling object at compile-time so whatever you do with the object later, it will propably not work.
c) it would be easier/better if you'd just pass the object to the constructor or the method, like:
Class1 c1 = new Class1(object1);
Obviously i don't know the exact details of your situation but this really seems like you need to rethink your structure a bit.
This could easily be done if proper inheritance is structured.
Consider looking into an abstract class and classes that inherit from said abstract class. You might even be able to accomplish the same thing with interfaces.