2

可以在 C# 中动态实现接口,而无需使用反射发出代码,也许在 DLR 的帮助下。

我的意思是创建一个允许我们执行以下操作的工厂:

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

无论是罗斯林的方式。

4

2 回答 2

1

我可能错了,但你似乎在寻找 Mixins。

它们在 C# 中不受官方支持,但幸运的是有 re-mix 项目(re-motion 的一部分)

我过去用过它,效果很好,这里有一个例子:

/// <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,但它可以被强制转换为它并被视为已实现。

高级用法允许您在应用程序的生命周期内修改新创建对象的类型。

于 2012-09-19T14:34:17.717 回答
0

可以在 C# 中动态实现接口,而无需使用反射发出代码,也许在 DLR 的帮助下。

是的,我会这么认为。Bill Wagner 有一篇名为实现动态接口的文章。它演示了如何使用IDynamicMetaObjectProvide接口,特别是DynamicMetaObject类来滚动你自己的动态对象。然而,它是一个有点复杂的概念,在某些时候需要一些反射来将接口的成员连接到相应的 DLR 表示。

您不能使用已经存在的动态对象,ExpandoObject因为实现的接口(实际上只有一个接口)不能动态更改。

于 2012-09-19T16:27:22.783 回答