Detect if a method was overridden using Reflection (C#)
Given the type Test1
, you can determine whether it has its own implementation declaration of TestMe
:
typeof(Test1).GetMethod("TestMe").DeclaringType == typeof(Test1)
If the declaration came from a base type, this will evaluate false.
Note that since this is testing declaration, not true implementation, this will return true if Test1
is also abstract and TestMe
is abstract, since Test1
would have its own declaration. If you want to exclude that case, add && !GetMethod("TestMe").IsAbstract
Test if a method is an override?
You can use MethodInfo.DeclaringType to determine if the method is an override (assuming that it's also IsVirtual = true
).
From the documentation:
...note that when B overrides virtual
method M from A, it essentially
redefines (or redeclares) this method.
Therefore, B.M's MethodInfo reports
the declaring type as B rather than A,
even though A is where this method was
originally declared...
Here's an example:
var someType = typeof(BabyFoo);
var mi = someType.GetMethod("GimmeIntPleez");
// assuming we know GimmeIntPleez is in a base class, it must be overriden
if( mi.IsVirtual && mi.DeclaringType == typeof(BabyFoo) )
{ ... }
How to detect if virtual method is overridden in c#
Check this out: Detect if a method was overridden using Reflection (C#)
Reflection would be the only way to do this at runtime. This should come with a health warning however, it should be considered a Very Bad Idea™ from an OOP perspective. A base class should not generally know or care how a derived class is implemented.
How to check if method is overridden inside a type ? Reflection C#
You can use the binding flags to your advantage:
var t = typeof(mytype).GetMethod(
"Equals",
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly
);
Then t
is not null
if and only if mytype
overrides Equals
.
Test whether virtual method has been overridden
public class BaseClass
{
public bool SupportsA
{
get { return (this.GetType().GetMethod("A").DeclaringType == typeof(BaseClass)); }
}
public virtual void A()
{
// Null default implementation.
}
}
Determine whether a C# method has keyword 'override' using Reflection
Well, I don't see how that would come into play either. Your code there does indeed determine whether a method is defined or overriden.
In the case of hiding, the declaring type is the one that hides the method via new
.
In the case of generics, all methods are defined by the template class.
How to determine if the MethodInfo is an override of the base method
Check its DeclaringType
property.
if (methodInfo.DeclaringType == typeof(Foo)) {
// ...
}
Is there a way to override a method with reflection?
The first part of this answer is wrong, I'm only leaving it so that the evolution in the comments makes sense. Please see the EDIT(s).
You're not looking for reflection, but emission (which is the other way around).
In particular, there's a method that does just what you want, lucky you!
See TypeBuilder.DefineMethodOverride
EDIT:
Writing this answer, I just remembered that re-mix allows you to do this too. It's way harder though.
Re-mix is a framework that "simulates" mixins in C#. In its basic aspect, you can think of it as interfaces with default implementations. If you go further, it becomes much more than that.
EDIT 2: Here is an example of use for re-mix (implementing INotifyPropertyChanged on a class that doesn't support it, and has no idea of mixins).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Remotion.Mixins;
using System.ComponentModel;
using MixinTest;
[assembly: Mix(typeof(INPCTester), typeof(INotifyPropertyChangedMixin))]
namespace MixinTest
{
//[Remotion.Mixins.CompleteInterface(typeof(INPCTester))]
public interface ICustomINPC : INotifyPropertyChanged
{
void RaisePropertyChanged(string prop);
}
//[Extends(typeof(INPCTester))]
public class INotifyPropertyChangedMixin : Mixin<object>, ICustomINPC
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string prop)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(prop));
}
}
}
public class ImplementsINPCAttribute : UsesAttribute
{
public ImplementsINPCAttribute()
: base(typeof(INotifyPropertyChangedMixin))
{
}
}
//[ImplementsINPC]
public class INPCTester
{
private string m_Name;
public string Name
{
get { return m_Name; }
set
{
if (m_Name != value)
{
m_Name = value;
((ICustomINPC)this).RaisePropertyChanged("Name");
}
}
}
}
public class INPCTestWithoutMixin : ICustomINPC
{
private string m_Name;
public string Name
{
get { return m_Name; }
set
{
if (m_Name != value)
{
m_Name = value;
this.RaisePropertyChanged("Name");
}
}
}
public void RaisePropertyChanged(string prop)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
And the test:
static void INPCImplementation()
{
Console.WriteLine("INPC implementation and usage");
var inpc = ObjectFactory.Create<INPCTester>(ParamList.Empty);
Console.WriteLine("The resulting object is castable as INPC: " + (inpc is INotifyPropertyChanged));
((INotifyPropertyChanged)inpc).PropertyChanged += inpc_PropertyChanged;
inpc.Name = "New name!";
((INotifyPropertyChanged)inpc).PropertyChanged -= inpc_PropertyChanged;
Console.WriteLine();
}
static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("Hello, world! Property's name: " + e.PropertyName);
}
//OUTPUT:
//INPC implementation and usage
//The resulting object is castable as INPC: True
//Hello, world! Property's name: Name
Please note that:
[assembly: Mix(typeof(INPCTester), typeof(INotifyPropertyChangedMixin))]
and
[Extends(typeof(INPCTester))] //commented out in my example
and
[ImplementsINPC] //commented out in my example
Have the exact same effect. It is a matter of where you wish to define that a particular mixin is applied to a particular class.
Example 2: overriding Equals and GetHashCode
public class EquatableByValuesMixin<[BindToTargetType]T> : Mixin<T>, IEquatable<T> where T : class
{
private static readonly FieldInfo[] m_TargetFields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
bool IEquatable<T>.Equals(T other)
{
if (other == null)
return false;
if (Target.GetType() != other.GetType())
return false;
for (int i = 0; i < m_TargetFields.Length; i++)
{
object thisFieldValue = m_TargetFields[i].GetValue(Target);
object otherFieldValue = m_TargetFields[i].GetValue(other);
if (!Equals(thisFieldValue, otherFieldValue))
return false;
}
return true;
}
[OverrideTarget]
public new bool Equals(object other)
{
return ((IEquatable<T>)this).Equals(other as T);
}
[OverrideTarget]
public new int GetHashCode()
{
int i = 0;
foreach (FieldInfo f in m_TargetFields)
i ^= f.GetValue(Target).GetHashCode();
return i;
}
}
public class EquatableByValuesAttribute : UsesAttribute
{
public EquatableByValuesAttribute()
: base(typeof(EquatableByValuesMixin<>))
{
}
}
That example is my implementation of the hands-on lab given with re-mix. You can find more information there.
Related Topics
Why Must a Lambda Expression Be Cast When Supplied as a Plain Delegate Parameter
How to Calculate Wpf Textblock Width for Its Known Font Size and Characters
C#: How to Make It Harder for Hacker/Cracker to Get Around or Bypass the Licensing Check
There Is No Argument Given That Corresponds to the Required Formal Parameter - .Net Error
Read Connection String from Web.Config
C# Elegant Way to Check If a Property's Property Is Null
How to Automatically Scroll to the Bottom of a Multiline Text Box
How to Make Two Transparent Layer with C#
How to Set Up Automapper in ASP.NET Core
Dictionary Returning a Default Value If the Key Does Not Exist
Understanding Async/Await in C#
How to Enable Nuget Package Restore in Visual Studio
Websocket Server: Onopen Function on the Web Socket Is Never Called
Forms Authentication Across Sub-Domains
Xml-Selectnodes with Default-Namespace via Xmlnamespacemanager Not Working as Expected