La primera parte de esta respuesta es incorrecta, sólo estoy dejándolo de manera que la evolución en los comentarios tiene sentido. Por favor vea los EDIT (s).
usted no está buscando para la reflexión, pero emisión (que es a la inversa).
En particular, hay un método que hace exactamente lo que quiere, qué suerte!
Ver TypeBuilder.DefineMethodOverride
EDIT:
Escribir esta respuesta, acabo de recordar que re-mix le permite hacer esto también. Aunque es mucho más difícil.
Re-Mix es un marco que "simula" mixins en C#. En su aspecto básico, puede pensarlo como interfaces con implementaciones predeterminadas. Si vas más allá, se convierte en mucho más que eso.
EDIT 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 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;
}
}
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
Tienen exactamente el mismo efecto. Es una cuestión de dónde desea definir que una mezcla particular se aplica a una clase particular.
Ejemplo 2: Igual primordial 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 aplicación de las práctica de laboratorio se administran junto con la re-mezcla. Puede encontrar más información allí.
No, C# no se puede parchear, si esa es la pregunta ... –
@MarcGravell emisión permite eso. Además, volver a mezclar puede hacerlo también. ¡C# puede ser totalmente parchado! –
@Baboon respondió en su respuesta –