2012-09-19 60 views
2

可能在C#中動態實現接口,而無需使用反射發射代碼,也許藉助於DLR。動態實現C#接口是否可行

我的意思是創建一個工廠,使我們能夠做到以下幾點:

 IComparable comparable = factory.Create<IComparable>(); 

無論哪種方式羅絲琳。

+0

這聽起來有點舔什麼嘲笑框架對我做... –

+2

它應該怎麼做?這些方法應該什麼都不做?他們是否應該讓代表們瞭解這些方法的作用?他們是否應該有一個擁有方法但沒有實現接口的類?它是否應該找到一些能夠實現接口的隨機類? – Servy

+0

你的意思是說,沒有具體實現'IComparable'註冊或鏈接的方式? – Jodrell

回答

0

可能在C#中動態實現一個接口,而無需使用反射發射代碼,也許藉助於DLR。

是的,我會這麼認爲。比爾瓦格納有一篇名爲Implementing Dynamic Interfaces的文章。它演示瞭如何使用IDynamicMetaObjectProvide接口,尤其是DynamicMetaObject類來爲您推出非常自己的動態對象。然而,這是一個相當複雜的概念,並且在某些時候需要一些反思來將接口的成員連接到相應的DLR表示。

您不能使用已有的動態對象,如ExpandoObject,因爲實現的接口(實際上只有一個接口)不能動態更改。

1

我可能是錯的,但它似乎是在尋找Mixins。

他們沒有正式在C#的支持,幸好有the re-mix project

我已經在過去使用它(重新運動的一部分)和它的作品很好,這裏有一個例子:

/// <summary> 
    /// This <see cref="Mixin"/> is used to "automatically" implement <see cref="INotifyPropertyChanged"/> to a target class. 
    /// <para>It will also override <c>ToString()</c> to show it's possible.</para> 
    /// </summary> 
    /// <example>This example adds <see cref="INotifyPropertyChanged"/> to <see cref="INPCTester"/> 
    /// <code> 
    /// [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"); 
    ///    } 
    ///   } 
    ///  } 
    /// } 
    /// 
    /// class Program 
    /// { 
    ///  static void Main(string[] args) 
    ///  { 
    ///   INPCImplementation(); 
    ///  } 
    ///  
    ///  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!"; 
    ///   Console.WriteLine(inpc.ToString()); 
    ///   ((INotifyPropertyChanged)inpc).PropertyChanged -= inpc_PropertyChanged; 
    ///   Console.WriteLine(); 
    ///  } 
    /// } 
    /// 
    /// //Outputs: 
    /// // 
    /// //INPC implementation and usage 
    /// //The resulting object is castable as INPC: True 
    /// //Hello, world! Property's name: Name 
    /// //Modified tostring! 
    /// </code> 
    /// </example>  
    /// <remarks> 
    /// The <see cref="ImplementsINPCAttribute"/> is syntactic sugar for 
    /// <para> <c>[Uses(typeof(INotifyPropertyChangedMixin))]</c> on top of the target class</para> 
    /// <para>Which is equivalent to: </para> 
    /// <para> <c>[assembly: Mix(typeof(INPCTester), typeof(INotifyPropertyChangedMixin))]</c> outside the namespace.</para> 
    /// <para>or <c>[Extends(typeof(INPCTester))]</c> on top of the mixin class</para> 
    /// </remarks> 
    public class INotifyPropertyChangedMixin : Mixin<object>, ICustomINPC 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     /// <inheritdoc /> 
     public void RaisePropertyChanged(string prop) 
     { 
      PropertyChangedEventHandler handler = this.PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(prop)); 
      } 
     } 

     /// <inheritdoc /> 
     [OverrideTarget] 
     public new string ToString() 
     { 
      return "Modified tostring!"; 
     } 
    } 

    public class ImplementsINPCAttribute : UsesAttribute 
    { 
     public ImplementsINPCAttribute() 
      : base(typeof(INotifyPropertyChangedMixin)) 
     { 

     } 
    } 

請注意,儘管INPCTester類沒有實現INotifyPropertyChanged,但它可以被轉換爲它,並被視爲它。

高級用法允許您在應用程序的生命週期中修改新創建的對象的類型。

+0

好的,謝謝,但是在某些地方你已經創建了一個對象INotifyPropertyChangedMixin,唯一動態的方法是通過反射發射代碼,然後注入代碼。 –