2015-09-11 3 views
0

Я прочитал кое-что о ExpandoObject и могу расширить его с помощью свойств, полей, методов.ExpandoObject add Свойство с «дополнительным» -кодом

//that's how to add a property to an ExpandoObject. 
dynamic x = new ExpandoObject(); 
x.NewProp = string.Empty; 

Но иногда было бы удобно добавить свойство с помощью какого-либо «лишнего кода».

class sample 
{ 
    // a sample field. 
    public string sampleString{get;set} 
    // a sample property with some "extra code" 
    private string s; 
    public string sampleExtraString 
    { 
     get{return s;} 
     set{s=value;Console.WriteLine(s);} 
    } 
} 

Теперь мой вопрос, как я могу добавить собственность к ExpandoObject, который будет выполнять свою Console.WriteLine(s);, например, на съемочной площадке.

+0

Проделав некоторое чтение на expandoObjects, я не уверен, если это возможно сделать то, что вы просите. Лучше всего было бы добавить событие в файл expandoObject, к которому вы передаете свою новую строку, это может затем запустить некоторый код, а также сохранить строку в expandoObject. –

+0

например ... Я хочу выполнить некоторый код после появления в коде кода 'x.NewProp = ...', как это возможно в свойствах в «написанных» классах. (Clear?) – leAthlon

ответ

1

Я думаю, что лучший подход будет использовать DynamicObject, которые можно перехватить вызовы для
методов и свойств.
Это простой пример: более надежный не использовал бы отражение для выполнения операций set/get для свойства, а скорее с помощью reflection.Emit или любой скомпилированной стратегии операции.

public class Sample 
{ 
    public string SampleExtraString { get; set; } 
} 

public class Factory 
{ 
    public class ExtraPropertyObject<T> : DynamicObject 
    { 
     private readonly T instance = default(T); 
     private readonly Type instanceType = null; 

     public ExtraPropertyObject(T instance) { 
      this.instance = instance; 
      instanceType = instance.GetType(); 
     } 

     public override bool TrySetMember(SetMemberBinder binder, object value) { 
      PropertyInfo prop = null; 

      if (binder.Name.Equals("SampleExtraString")) { 
       Console.WriteLine(value); 
      } 

      prop = instanceType.GetProperty(binder.Name); 

      if (prop != null) { 
       try { 
        prop.SetValue(instance, value); 
        return true; 
       } 
       catch (Exception ex) { 

       } 
      } 

      return false; 
     } 

     public override bool TryGetMember(GetMemberBinder binder, out object result) { 
      var prop = instanceType.GetProperty(binder.Name); 

      if (prop != null) { 
       try { 
        result = prop.GetValue(instance); 
        return true; 
       } 
       catch (Exception ex) { 

       } 
      } 

      result = null; 
      return false; 
     } 
    } 

    public static dynamic CreateInstance<TInstance>() where TInstance : class, new() { 
     return new ExtraPropertyObject<TInstance>(new TInstance()); 
    } 

    public static dynamic CreateInstance<TInstance>(TInstance instance) { 
     return new ExtraPropertyObject<TInstance>(instance); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) { 
     var instance = Factory.CreateInstance<Sample>(); 
     instance.SampleExtraString = "value"; 
     Console.WriteLine("Get Operation: {0}", instance.SampleExtraString); 
    } 
} 
2

ExpandoObject реализует INotifyPropertyChanged, как описано here
(в нижней части страницы)

((INotifyPropertyChanged)x).PropertyChanged += 
     new PropertyChangedEventHandler(Expando_PropertyChanged); 
    x.NewProp = string.Empty; 


private static void Expando_PropertyChanged(object sender, 
    PropertyChangedEventArgs e) 
{ 
    Console.WriteLine("{0} has changed.", e.PropertyName); 
}