Есть ли способ «переопределить» метод с отражением?

StackOverflow https://stackoverflow.com//questions/9684804

  •  13-12-2019
  •  | 
  •  

Вопрос

без наследства, но только с отражением можно динамически изменять код метода в C #?

что-то вроде:

nameSpaceA.Foo.method1 = aDelegate;
.

Я не могу изменить / редактировать класс FO.

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

Моя последняя цель - изменить динамичный код:

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

в System.xml.xsl.runtime.xslconvert.cs

Чтобы повернуть:

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

в:

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

Это было полезно?

Решение

Первая часть этого ответа неверна, я только оставляю его так, чтобы эволюция в комментариях имеет смысл. Пожалуйста, смотрите редактирование (ы).

Вы не ищете отражение, но выбросы (который находятся наоборот).

В частности, есть метод, который вы хотите, что вы хотите, повезло!

см. см. typebuilder.definemethodoverride

<Сильные> Редактировать:
Написав этот ответ, я только что вспомнил, что
Re-Micking позволяет вам сделать это тоже. Это сложнее, хотя.

RE-MIX - это каркас, которая «моделирует» миксики в C #. В своем основном аспекте вы можете думать об этом как об интерфейсах с реализациями по умолчанию. Если вы пойдете дальше, это становится намного больше, чем это.

Редактировать 2: Вот пример использования для повторной смеси (реализация inotifyPropertyChanged на классе, который не поддерживает его, и не имеет представления о смеси).

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

и тест:

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
.

Обратите внимание, что:

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

и

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

и

[ImplementsINPC] //commented out in my example
.

имеют тот же тот же эффект. Это вопрос того, где вы хотите определить, что определенный микс применяется к определенному классу.

<Сильный> Пример 2: Переопределение равных и 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<>))
        {

        }
    }
.

Этот пример - моя реализация ручной лаборатории, данной с повторной смеси. Вы можете найти больше информации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top