2011-02-06 2 views
1

Я работаю над проектом, где мне нужно поставить в очередь ряд изменений свойств. Пусть у меня есть:C# Отложенное свойство Setting

public class foo 
{ 
    string bar { get; set; } 
    int bar1 { get; set } 
} 

Я хочу иметь некоторый код, который выглядит следующим образом:

//Store value set actions in a queue 
foo.SetValue(bar, "abc"); 
foo.SetValue(bar1, 123); 

//Preview changes 
foreach(Item change in foo.ChangeQueue) 
{ 
    Console.Write(change.PropertyName.ToString()); 
    Console.Write(change.Value.ToString()); 
} 

//Apply actions 
foo.CommitChanges(); 

Что является лучшим способом для достижения этой цели?

+0

Значит, вы заботитесь о самой последней настройке, или вам нужно поставить очередь всех изменений в конкретное свойство? – Gabe

+0

Все изменения – Matt

ответ

1

"Типобезопасный" версия, которая использует обратные вызовы. Это не приведет к автоматическому удалению дубликатов настроек. Он также не использует рефлексию, и поэтому ошибки компиляции не будут устранены. Этот метод можно было бы расширить, чтобы потребовать «имя» и удалить дубликаты, используя поддержку словаря (согласно ответу Акаша) или разрешить «сеттер» возвращать значение (например, успех или неудачу, или старое значение, или еще что-то).

interface Setter { 
    void Apply(); 
} 
class Setter<T> : Setter { 
    public T Data; 
    public Action<T> SetFn; 
    public void Apply() { 
     SetFn(Data); 
    } 
} 

List<Setter> changeQueue = new List<Setter>(); 

void SetValue<T>(Action<T> setFn, T data){ 
    changeQueue.Add(new Setter<T> { 
     Data = data, 
     SetFn = setFn, 
    }); 
} 

void ApplyChanges(){ 
    foreach (var s in changeQueue){ 
     s.Apply(); 
    } 
} 

// .. later on 
SetValue(x => System.Console.WriteLine(x), "hello world!"); 
ApplyChanges(); 

Этот метод может быть также использован тривиальным «снаружи» объекты под контролем, потому что все операции в потенциальных замыканий.

Счастливое кодирование.

+0

Можете ли вы уточнить: SetValue (x => System.Console.WriteLine (x), «hello world!»); ? Я не мог заставить это работать немедленно, я должен что-то упустить. – Matt

+0

'SetValue' (на самом деле неверно названо) - для выполнения этого действия требуется действие (когда вызывается ApplyChanges). В этом случае я просто побочный эффект для записи на консоль - это может быть реальным примером:' SetValue (x => myObject.IntProperty = x, 10) '(обратите внимание, что он * фиксирует * целевой объект, значение которого будет установлено в закрытии). Тип 'x' - это тип переданного значения (строка в моем коде, int в примере в комментарии) и выводится из определения' T' в определении метода (оба T должны быть одинаковыми, поэтому C# пытается сделайте это совпадением). –

+0

@Matt Если этот метод является частью класса, также можно безопасным образом передать текущий класс в действие (добавить параметр второго типа в Setter), например. с некоторой переработкой: 'myObject.SetValue ((x, o) => o.Property = x, ...)', что позволяет избежать замыкания (где o - myObject, но с другим именем). –

2

Вы можете использовать Dictionary<string,object> как ChangeQueue для хранения ваших значений.

Вы можете перебирать, как,

foreach(KeyValuePair<string,object> item in ChangeQueue){ 
    Console.WriteLine(item.Key);// name of property 
    Console.WriteLine(item.Value); // value of property 
} 


public void SetValue(string name, object value){ 
    PropertyInfo p = this.GetType().GetProperty(name); 

    // following convert and raise an exception to preserve type safety 
    ChangeQueue[name] = Convert.ChangeType(value,p.PropertyType); 
} 

public void ApplyChanges(){ 
    foreach(KeyValuePair<string,object> item in ChangeQueue){ 
     PropertyInfo p = this.GetType().GetProperty(item.Key); 
     p.SetValue(this, item.Value, null); 
    } 
} 
+1

И если все изменения необходимо отслеживать или изменять порядок, 'IEnumerable >' является почти прямой заменой словаря выше. –

+0

Это выглядит нормально. Но нет безопасности типа. – Matt

+0

Я обновил свой код, чтобы ввести тип безопасности –

Смежные вопросы