Reputation: 3941
It is possible dynamically implement an interface in C# without emitting code using reflection, maybe with the help of DLR.
I mean create a factory that allow us to do the following:
IComparable comparable = factory.Create<IComparable>();
Either Roslyn way.
Upvotes: 2
Views: 2931
Reputation: 106816
It is possible dynamically implement an interface in C# without emitting code using reflection, maybe with the help of DLR.
Yes, I would think so. Bill Wagner has an article named Implementing Dynamic Interfaces. It demonstrates how you can use IDynamicMetaObjectProvide
interface and in particular the DynamicMetaObject
class to roll you very own dynamic object. However, it is a somewhat complex concept and at some point it will require some reflection to hook up the members of the interface to the corresponding DLR representation.
You cannot use an already existing dynamic object like ExpandoObject
because the implemented interfaces (actually just one interface) cannot be changed dynamically.
Upvotes: 0
Reputation: 16618
I may be wrong, but it you seem to be looking for Mixins.
They are not officially supported in C#, but fortunately there's the re-mix project (part of re-motion)
I've used it in the past and it works well, here's an example:
/// <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))
{
}
}
Please notice that while the INPCTester class does not implement INotifyPropertyChanged, it can be casted to it and treated as if it did.
Advanced usage allows you to modify types for newly created objects during the lifetime of the application.
Upvotes: 1