I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
Related
I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
Let's assume that I have two class.
public class A {...}
public class B : A {...}
What I want is to achieve is to override an extension function for both type.
public static void HelperExtension(this A a) {...}
public static void HelperExtension(this B b) {...}
I know that they are not virtual functions or behave like them. However I really wonder compiler behavior in this case.
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
This is not overriding - it is overloading, if anything.
It is fine - since the signatures are different, the compiler will not have any problem compiling it, even in the same namespace.
However, which extension method will be called depends on the exact type of the variable.
Now:
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
Without casting this is not possible. The extension is bound to the exact type that is being extended, so you need to have the exact type in order to call an extension on it.
This is why most of LINQ is defined on IEnumerable<T>.
As you said, there is no way of just making the extension virtual.
You could implement the entire virtual method pattern yourself through static methods but I have a strong feeling that's not going to be of any practical use to you, it's more of an interesting theoretical solution as the work involved would be prohibitive for something this simple.
If there are a fixed, finite number of possible sub classes you could have the first method have something like:
public static void HelperExtension(this A a)
{
B b = a as B;
if(b != null)
HelperExtension(b);
else
//the rest of the method.
}
You could use a Switch or even a Dictionary<Type, Action<A>> if you have a lot of subclasses, but it would be tedious, hard to maintain, and not support arbitrary inheritors not known at compile time.
Another option is to essentially leverage the compiler's functionality at compile time through the use of dynamic. I strongly advice avoiding it whenever possible, but in this particular case it would allow you to have a single public extension on A, a bunch of private static methods (with a different name) for each sub type, and then a single dispatch call:
public static void HelperExtension(this A a)
{
ExtenstionImplementation((dynamic)a);
}
private static void ExtenstionImplementation(A a){...}
private static void ExtenstionImplementation(B a){...}
private static void ExtenstionImplementation(C a){...}
I recently faced a similar problem. I have a third-party class library containing a hierarchy of class (let's say IBase, Base and Derived, where IBase is actually an interface).
public interface IBase {...}
public class Base : IBase {...}
public class Derived : Base {...}
Then, I have a class of mine which holds a reference ext to IBase. The concrete type of ext may be Base as well as Derived.
public class MyClass {
// other stuff
public IBase ext;
}
What I actually needed was a virtual method AddedMethod() defined within IBase and overridden in each descendant class, but that wasn't viable. So, one could be tempted to define a class containing a set of overloaded extension methods:
public static class MyExtensions
{
public static void AddedMethod(this IBase arg) {...}
public static void AddedMethod(this Base arg) {...}
public static void AddedMethod(this Derived arg) {...}
}
then, call ext.AddedMethod() on MyClass objects. This doesn't work: as extension methods are statically bound, the first method (i.e. AddedMethod(this IBase arg)) gets always called, regardless the actual type of ext.
The problem can be bypassed by defining a single extension method on IBase, then by using reflection to select the correct instance of a private static method whose argument type matches the actual type passed to the extension method:
public static class MyExtensions
{
// just one extension method
public static void AddedMethod(this IBase arg){
// get actual argument type
Type itsType = arg.GetType();
// select the proper inner method
MethodInfo mi = typeof(MyExtensions).GetMethod("innerAddedMethod",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new Type[] { itsType },
null);
// invoke the selected method
if (mi != null) {
mi.Invoke(null, new object[] { arg });
}
}
private static void innerAddedMethod(Base arg) {
// code for Base type arg
}
private static void innerAddedMethod(Derived arg) {
// code for Derived type arg
}
Whether a new derived class Derived2 should be added to the IBase hierarchy, we'll have to simply add to MyExtensions class an overloaded innerAddedMethod() which takes Derived2 as its argument.
Example:
namespace MyProgram.Testing
{
public class Test1
{
public void TestMethod()
{
String actualType = this.GetType().FullName.ToString();
return;
}
public static String GetInheritedClassName()
{
return System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.FullName;
}
}
public class Test2 : Test1
{
}
public class Test3
{
String test2ClassName = Test2.GetInheritedClassName();
}
}
Anyway, I want it to return "MyProgram.Testing.Test2" but instead Test2.GetInheritedClassName() returns "MyProgram.Testing.Test1". What do I have to put into that static class to get it to return that (if possible)?
It's not possible. When you call Test2.GetInheritedClassName, it's actually Test1.GetInheritedClassName that is called, because Test2.GetInheritedClassName doesn't really exists (btw, some tools like Resharper would show a warning: Access to a static member of a type via a derived type)
Static members don't participate in inheritance, which is kind of logical since inheritance only makes sense when you're dealing with instances...
The code that's printing out the type is the base-class method. Except for rare Reflection scenarios such as you provide above, execution wouldn't be affected by whether the method is called using the derived type or the base type, so the system makes no distinction.
You could, however, get around this by defining a generic base type:
class ClassNameTesterBase<T>where T:ClassNameTester<T>
{
public static String getName() { return (typeof(T)).Name; }
}
and then defining the other types of interest:
class ClassNameTester1<T> : ClassNameTesterBase<T> ...
class ClassNameTester2<T> : ClassNameTester1<T> ...
One may then if desired define leaf classes:
class ClassNameTester1 : ClassNameTester1<ClassNameTester1> { }
class ClassNameTester2 : ClassNameTester2<ClassNameTester2> { }
One slight caveat here is that ClassNameTester2 derives its innards from from ClassNameTester1<T> but is not substitutable for anything having to do with the ClassNameTester1<ClassNameTester1>; if it's being used as a static class, though, that shouldn't be a problem.
I've got an abstract class like this;
public abstract PropertyBase
{
public static System.Type GetMyType()
{
return !!!SOME MAGIC HERE!!!
}
}
I'd like to subclass it, and when I call the static GetMyType(), I'd like to return the subclass's type. So if I declare a subtype;
public class ConcreteProperty: PropertyBase {}
then when I call
var typeName = ConcreteProperty.GetMyType().Name;
I expect 'typeName' to be set to "ConcreteProperty." I suspect there's no way to do it, but I'm interested if anyone out there knows a way to get this info.
(The particular problem I'm trying to solve is the verbosity of dependency properties in WPF; I'd love to be able to do something like this;
class NamedObject : DependencyObject
{
// declare a name property as a type, not an instance.
private class NameProperty : PropertyBase<string, NamedObject> { }
// call static methods on the class to read the property
public string Name
{
get { return NameProperty.Get(this); }
set { NameProperty.Set(this, value); }
}
}
And I almost have an implementation, but I can't quite get the info I need out of my NameProperty class.)
You can partially achieve (1-level of inheritance deep) using generics:
class PropertyBase<T>
{
public static Type GetMyType() { return typeof (T); }
}
// the base class is actually a generic specialized by the derived class type
class ConcreteProperty : PropertyBase<ConcreteProperty> { /* more code here */ }
// t == typeof(ConcreteProperty)
var t = ConcreteProperty.GetMyType();
The subclassing bit will not work, because a static method is tied to a type. It is a method of a type, not a method of an instance. The subtype does not contain the static methods of a base type, because they are different types and the static method is tied to the base type. Even though the compiler might allow you to call a static method of a base class as through a derived class, it will in reality call the method from the base class. It's just syntax sugar. For the same reason you cannot "override" static methods in subclasses because it would make little sense.
Just wondering why would need to do something like this?
var typeName = ConcreteProperty.GetMyType().Name;
Anyhow you know the type while calling the method, you can simply do this as well..
var typeName = typeof(ConcreteProperty).Name;
Just in case you need to do this, you can use "shadowing" to override the implementation of base class in child class.
public class ConcreteProperty : PropertyBase {
public new static Type GetMyType {
//provide a new implementation here
}
}
Is there a simple way to implement this, and if possible without instanciating an object :
interface I
{
static string GetClassName();
}
public class Helper
{
static void PrintClassName<T>() where T : I
{
Console.WriteLine(T.GetClassName());
}
}
Try an extension method instead:
public interface IMyInterface
{
string GetClassName();
}
public static class IMyInterfaceExtensions
{
public static void PrintClassName<T>( this T input )
where T : IMyInterface
{
Console.WriteLine(input.GetClassName());
}
}
This allows you to add static extension/utility method, but you still need an instance of your IMyInterface implementation.
You can't have interfaces for static methods because it wouldn't make sense, they're utility methods without an instance and hence they don't really have a type.
You can not inherit static methods. Your code wouldn't compile in any way, because a interface can't have static methods because of this.
As quoted from littleguru:
Inheritance in .NET works only on
instance base. Static methods are
defined on the type level not on the
instance level. That is why overriding
doesn't work with static
methods/properties/events...
Static methods are only held once in
memory. There is no virtual table etc.
that is created for them.
If you invoke an instance method in
.NET, you always give it the current
instance. This is hidden by the .NET
runtime, but it happens. Each instance
method has as first argument a pointer
(reference) to the object that the
method is run on. This doesn't happen
with static methods (as they are
defined on type level). How should
the compiler decide to select the
method to invoke?
I also tried to setup a static method on an interface a little while ago, not sure why now. I did bookmark this so maybe it helps:
Interface with a static method by using extension methods
If you're just after the type name, you can just do this:
public class Helper
{
static void PrintClassName<T>()
{
Console.WriteLine(typeof(T).Name);
}
}
Declaring a static property, event or method on an interface definition is not considered a legal definition. This is because interfaces are considered contracts and as such, represent something that will be implemented by every client instance of that interface.
A static declaration essentially states that the static member does not require a physical client implementation in order to execute the required functionality and this falls short of the general concept of interfaces: providing a proven contract.
The answer is a qualified "not really but Sort Of". You can provide a static extension method to all implementors of a given interface and can then call this from your implementer in a property or another method. As an example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace InterfacesWithGenerics
{
class Program
{
static void Main(string[] args)
{
Helper.PrintClassName<Example>(new Example());
Console.ReadLine();
}
}
public class Example : I
{
#region I Members
public string ClassName
{
get { return this.GetClassName(); }
}
#endregion
}
public interface I
{
string ClassName { get; }
}
public class Helper
{
public static void PrintClassName<T>(T input) where T : I
{
Console.WriteLine( input.GetClassName()) ;
}
}
public static class IExtensions
{
public static string GetClassName(this I yourInterface)
{
return yourInterface.GetType().ToString();
}
}
}
Here we have an interface (I) which defines the property we care about and a static extension method (GetClassName) which is applied to all members of its type which does the grunt work of getting the information we want. We Have a Class (Example) which implements the I interface so when we call our static helper class passing in an instance of Example, it runs the static method against it. Unfortunately it is not valid to reference the type T directly within the method itself as a variable, you'll have to pass an instance into the application.
You could define the className as attribute on the specific class. This is the preferred ay to store metadata in .net. This way you can query the attribute for the given class and you do not need an instance.
Yes, you can - sort-of - if you don't mind defining new types that proxy instance calls to static methods:
While an interface can only declare instance members, you can use a couple of simple tricks with C#'s generics, without needing reflection, to accomplish what you're after (and without resorting to Java-style AbstractFactoryBeanFactory design-pattern overuse).
What we can do, is define a separate struct (i.e. a value-type) that contains instance members that call-into the static members we want.
So if we have this interface:
interface IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance();
}
...and we want to do something like this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
{
T.DoSomethingWithoutAnObjectInstance();
}
...then we can do this:
void AGenericMethodThatDoesntHaveAnInstanceOfT<T>()
where T : struct, IStaticFunctionality
{
T t = default;
t.DoSomethingWithoutAnObjectInstance();
// Note the above code uses `T t default;` instead of `T t = new T()`.
// This is because the C# compiler currently replaces `new T()` with `Activator.CreateInstance<T>()` in the generated bytecode.
// This has poor performance compared to `default(T)` or a normal non-generic constructor call, but the compiler does this because it's a workaround for a design-bug back in C# 6.0: https://devblogs.microsoft.com/premier-developer/dissecting-the-new-constraint-in-c-a-perfect-example-of-a-leaky-abstraction/
}
So if we have different types with the static void DoSomethingWithoutAnObjectInstance method, we just need to define struct implementations of IStaticFunctionality for each of those types:
class Foo
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("foo");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Foo.DoSomethingWithoutAnObjectInstance();
}
}
class Bar
{
public static void DoSomethingWithoutAnObjectInstance()
{
Console.WriteLine("bar");
}
struct Static : IStaticFunctionality
{
void DoSomethingWithoutAnObjectInstance() => Bar.DoSomethingWithoutAnObjectInstance();
}
}
So then a call-site for AGenericMethodThatDoesntHaveAnInstanceOfT<Foo> would actually look like:
AGenericMethodThatDoesntHaveAnInstanceOfT<Foo.Static>();