Pregunta

Sin heredar, pero solo con la reflexión, ¿es posible cambiar dinámicamente el código de un método en C #?

algo como:

nameSpaceA.Foo.method1 = aDelegate;

No puedo cambiar / editar la clase FOO.

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

Mi objetivo final es cambiar Dinamicaly el código de:

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

en system.xml.xsl.runtime.xslconvert.cs

a girar:

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

en:

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

¿Fue útil?

Solución

La primera parte de esta respuesta es incorrecta, solo lo estoy dejando para que la evolución en los comentarios tenga sentido. Por favor, vea la (s) edición (s).

No está buscando reflexión, sino emisión (que es al revés).

En particular, hay un método que hace lo que quiere, afortunado de usted!

Consulte TypeBuilder.DefineMetHoDoverRide

Editar:
Escribiendo esta respuesta, acabo de recordar que
re-mezcle le permite hacer esto también. Sin embargo, es mucho más difícil.

volver a mezclar es un marco que "simula" Mixins en C #. En su aspecto básico, puede pensarlo como interfaces con implementaciones predeterminadas. Si vas más lejos, se vuelve mucho más que eso.

Editar 2: Aquí hay un ejemplo de uso para volver a mezclar (implementando inotifypropertychanged en una clase que no lo admite, y no tiene idea de mezcla).

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;
    }
}

y la prueba:

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

Tenga en cuenta que:

[assembly: Mix(typeof(INPCTester), typeof(INotifyPropertyChangedMixin))]

y

[Extends(typeof(INPCTester))] //commented out in my example

y

[ImplementsINPC] //commented out in my example

tener exactamente el mismo efecto. Es una cuestión de dónde desea definir que se aplica una mezcla particular a una clase en particular.

Ejemplo 2: Equals anulados y 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<>))
        {

        }
    }

Ese ejemplo es mi implementación del laboratorio práctico dado con re-mezclar. Puedes encontrar más información allí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top