有没有一种办法"越权QUOT;与反射的方法? [英] Is there a way to "override" a method with reflection?

查看:243
本文介绍了有没有一种办法"越权QUOT;与反射的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果没有继承,但只有与反思,才有可能动态改变的方法的code在C#?

是这样的:

  nameSpaceA.Foo.method1 = aDelegate;

我不能改变/编辑Foo类。

 命名空间nameSpaceA
{
  Foo类
  {
       私人无效方法1()
       {
           // ...一些code
       }
  }
}

我的最终目标是改变dynamicaly的code:

 公共静态的IList<&XPathNavigator的GT; EnsureNodeSet(IList的< XPathItem> listItems中);

在System.Xml.Xsl.Runtime.XslConvert.cs

打开:

 如果(!item.IsNode)
    抛出新XslTransformException(Res.XPath_NodeSetExpected,的String.Empty);

 如果(!item.IsNode)
    抛出新XslTransformException(Res.XPath_NodeSetExpected,item.value);


解决方案

这个答案的第一部分是错误的,我只是离开它,以便在评论进化是有道理的。请参阅编辑(S)。

您不是在寻找反映,但排放量(这是其他方式)。

在特定的,有不只是你想要什么方法,你真幸运!

请参阅TypeBuilder.DefineMethodOverride

编辑:结果
写这个答案,我只记得重新组合让你做这件事的。它的方法虽然很难

重新组合是模拟在C#中混入的框架。在其基本方面,你可以认为它是与默认实现接口。如果你走的更远,它变得远不止于此。

编辑2:下面是使用了重新组合的一个例子(在不支持它的类实现INotifyPropertyChanged的,并且没有混入的想法)

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用Remotion.Mixins;
使用System.ComponentModel;
使用MixinTest;[总成:混合(typeof运算(INPCTester)的typeof(INotifyPropertyChangedMixin))]命名空间MixinTest
{
    //[Remotion.Mixins.CompleteInterface(typeof(INPCTester))]
    公共接口ICustomINPC:INotifyPropertyChanged的
    {
        无效RaisePropertyChanged(字符串道具);
    }    // [扩展(typeof运算(INPCTester))]
    公共类INotifyPropertyChangedMixin:混入&LT​​;对象&gt ;, ICustomINPC
    {
        公共事件PropertyChangedEventHandler的PropertyChanged;        公共无效RaisePropertyChanged(字符串道具)
        {
             PropertyChangedEventHandler处理器= this.PropertyChanged;
             如果(处理!= NULL)
             {
                 处理器(这一点,新PropertyChangedEventArgs(丙));
             }
        }
    }    公共类ImplementsINPCAttribute:UsesAttribute
    {
        公共ImplementsINPCAttribute()
            :基地(typeof运算(INotifyPropertyChangedMixin))
        {        }
    }    // [ImplementsINPC]
    公共类INPCTester
    {
        私人字符串m_Name;
        公共字符串名称
        {
            {返回m_Name; }
            组
            {
                如果(m_Name!=值)
                {
                    m_Name =价值;
                    ((ICustomINPC)本).RaisePropertyChanged(姓名);
                }
            }
        }
    }    公共类INPCTestWithoutMixin:ICustomINPC
    {
        私人字符串m_Name;
        公共字符串名称
        {
            {返回m_Name; }
            组
            {
                如果(m_Name!=值)
                {
                    m_Name =价值;
                    this.RaisePropertyChanged(姓名);
                }
            }
        }        公共无效RaisePropertyChanged(字符串道具)
        {
            PropertyChangedEventHandler处理器= this.PropertyChanged;
            如果(处理!= NULL)
            {
                处理器(这一点,新PropertyChangedEventArgs(丙));
            }
        }        公共事件PropertyChangedEventHandler的PropertyChanged;
    }
}

和测试:

 静态无效INPCImplementation()
        {
            Console.WriteLine(INPC实现和使用);            VAR INPC = ObjectFactory.Create< INPCTester>(ParamList.Empty);            Console.WriteLine(最终的目标是为浇注料INPC:+(INPC是INotifyPropertyChanged的));            ((INotifyPropertyChanged的)INPC).PropertyChanged + = inpc_PropertyChanged;            inpc.Name =新名字!
            ((INotifyPropertyChanged的)INPC).PropertyChanged - = inpc_PropertyChanged;
            Console.WriteLine();
        }静态无效inpc_PropertyChanged(对象发件人,PropertyChangedEventArgs E)
        {
            Console.WriteLine(你好!,世界属性的名称:+ e.PropertyName);
        }
//输出:
// INPC实现和使用
//生成的对象是作为浇注料INPC:真
//你好,世界!属性的名称:名称

请注意:

  [汇编:混合(typeof运算(INPCTester)的typeof(INotifyPropertyChangedMixin))]

  [扩展(typeof运算(INPCTester))] //在我的例子注释掉

  [ImplementsINPC] //在我的例子注释掉

有完全相同的效果。这是你希望定义一个特定的混入应用于特定类的问题。

例2:压倒一切的平等相待,GetHash code

 公共类EquatableByValues​​Mixin< BindToTargetType] T> :混入&LT​​;吨>中IEquatable< T>其中T:类
    {
        私人静态只读字段信息[] = m_TargetFields typeof运算(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic可);        布尔IEquatable< T> .Equals(T除外)
        {
            如果(其他== NULL)
                返回false;
            如果(Target.GetType()!= other.GetType())
                返回false;
            的for(int i = 0; I< m_TargetFields.Length;我++)
            {
                反对thisFieldValue = m_TargetFields [I] .GetValue(目标);
                反对otherFieldValue = m_TargetFields [I] .GetValue(其他);                如果(!等于(thisFieldValue,otherFieldValue))
                    返回false;
            }
            返回true;
        }        [OverrideTarget]
        新公共布尔等于(对象除外)
        {
            收益率((IEquatable< T>)这一点).Equals(其他为T);
        }        [OverrideTarget]
        公开新INT GetHash code()
        {
            INT I = 0;
            的foreach(在m_TargetFields字段信息F)
                I ^ = f.GetValue(目标).GetHash code();
            返回我;
        }
    }    公共类EquatableByValues​​Attribute:UsesAttribute
    {
        公共EquatableByValues​​Attribute()
            :基地(typeof运算(EquatableByValues​​Mixin<>))
        {        }
    }

这例子是我实现动手实验与重新组合给出的。你可以在那里找到更多的信息。

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

解决方案

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.

这篇关于有没有一种办法&QUOT;越权QUOT;与反射的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆