Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to "override" a method with reflection?

Tags:

Without inherit but only with reflection is it possible to dynamically change the code of a method in C#?

something like :

nameSpaceA.Foo.method1 = aDelegate; 

I cannot change/edit The Foo Class.

namespace nameSpaceA {   class Foo   {        private void method1()        {            // ... some Code        }   } } 

My final objective is to change dynamicaly the code of :

public static IList<XPathNavigator> EnsureNodeSet(IList<XPathItem> listItems); 

In System.Xml.Xsl.Runtime.XslConvert.cs

to turn :

if (!item.IsNode)     throw new XslTransformException(Res.XPath_NodeSetExpected, string.Empty);  

into :

if (!item.IsNode)     throw new XslTransformException(Res.XPath_NodeSetExpected, item.value);  
like image 702
Christophe Debove Avatar asked Mar 13 '12 13:03

Christophe Debove


People also ask

Can I override an override method?

You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.

Can we override sealed method in c#?

A method can also be sealed, and in that case, the method cannot be overridden. However, a method can be sealed in the classes in which they have been inherited. If you want to declare a method as sealed, then it has to be declared as virtual in its base class.

Can we override private methods in C#?

No, you can't override private elements, they're effectively final (because they're never visible from a subclass to be overriden.)

How do I override a Visual Studio method?

You can override virtual functions defined in a base class from the Visual Studio Properties window. To override a virtual function in the Properties window: In Class View, select the class. In the Properties window, select the Overrides button.


1 Answers

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.

like image 145
Louis Kottmann Avatar answered Sep 17 '22 14:09

Louis Kottmann