可以在C#中动态实现接口而不使用反射发出代码,也许可以借助DLR。
我的意思是创建一个允许我们执行以下操作的工厂:
IComparable comparable = factory.Create<IComparable>();
罗斯林的方式。
答案 0 :(得分: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,但它可以被转换为它并被视为它。
高级用法允许您在应用程序的生命周期内修改新创建的对象的类型。
答案 1 :(得分:0)
可以在C#中动态实现接口而不使用反射发出代码,也许可以借助DLR。
是的,我会这么认为。比尔瓦格纳有一篇名为Implementing Dynamic Interfaces的文章。它演示了如何使用IDynamicMetaObjectProvide
接口,特别是DynamicMetaObject
类来推送自己的动态对象。然而,这是一个有点复杂的概念,在某些时候,它需要一些反思来将接口的成员连接到相应的DLR表示。
您不能使用现有的动态对象,如ExpandoObject
,因为无法动态更改已实现的接口(实际上只有一个接口)。