2010-02-13 93 views
5

我在C#遊戲中做了一個實用程序調試類,我正在努力能夠監視和觀察屬性的值。是這樣的:改善財產監測代碼?

public static class Monitor 
{ 
    private static List<object> monitoredObjects; 

    public static void Initialize() 
    { 
    monitoredObjects = new List<object>(); 

    } 

    public static void Watch(object o) 
    { 
    monitoredObjects.Add(o); 
    } 

    public static void Unwatch(object o) 
    { 
    monitoredObjects.Remove(o); 
    } 

    public static void Draw(RenderWindow app) 
    { 
        //Not actual code, I actually draw this in game 
    foreach (object o in monitoredObjects) 
    Console.WriteLine(o.ToString()); 
    } 
} 

public class Property 
{ 
    private object obj; 
    private PropertyInfo propertyInfo; 

    public override string ToString() 
    { 
    return propertyInfo.Name + ": " + propertyInfo.GetValue(obj, null).ToString(); 
    } 

    public Property(object o, string property) 
    { 
    obj = o; 
    propertyInfo = o.GetType().GetProperty(property); 
    } 
} 

現在爲了監控財產,說我的遊戲的FPS,我必須做

Monitor.Watch(new Property(Game, "FPS")); 

豈不是有辦法以某種方式使這個簡單的使用?理想情況下,我想能夠做到

Monitor.Watch(Game.FPS); 

但由於我們可以在C#不store pointers to value types,我不知道我會怎麼做。也許使用閉包和lambda表達式?我早些時候提出過這個問題,但我不知道該怎麼做。任何其他方式來改善這一點?

感謝

回答

5

就個人而言,我會做什麼是返修您的顯示器類接受Func<string>作爲輸入,並返回一個可以用來「取消監視」類監測手柄。

通過這樣做,你可以寫:

var handle = Monitor.Watch(() => Game.FPS.ToString()); 
// later 
Monitor.Unwatch(handle); 

這可能看起來像:

public static class Monitor 
{ 
    private static Dictionary<IMonitorHandle, Func<string>> monitoredObjects; 

    public static void Initialize() 
    { 
     monitoredObjects = new Dictionary<IMonitorHandle, Func<string>>(); 
    } 

    public static IMonitorHandle Watch(Func<string> o) 
    { 
     var handle = new MonitorHandle(o); 
     monitoredObjects.Add(handle, o); 
     return handle; 
    } 

    public static void Unwatch(IMonitorHandle handle) 
    { 
     monitoredObjects.Remove(handle); 
    } 

    public static void Draw(RenderWindow app) 
    { 
     //Not actual code, I actually draw this in game 
     foreach (object o in monitoredObjects.Values) 
      Console.WriteLine(o()); // Execute to get value... 
    } 
} 

你需要實現對手柄的一些接口 - 但這真的可以是任何東西,因爲它只是一個用作哈希表查找以允許取消訂閱的對象。你只需要這個讓「Unwatch」工作,因爲你需要有一些方法來刪除委託,你可能想要匿名定義(如上所述)。

1

爲什麼你不使用INotifyPropertyChanged接口,只是在Monitor類中觸發事件,就像這樣......假設你的對象實現了接口......並且對象中的每個屬性都會引發一個'PropertyChanged'事件參數指示的值...這樣,它將是一個火災和遺忘的解決方案,而不是循環通過列表...當你調用實例化'監視'與作爲'初始化'參數的'RenderWindow'。還要注意的是「財產」類略作修改,包括get訪問到相關返回對象...

 
public static class Monitor 
{ 
    private static List monitoredObjects; 
    private static RenderWindow _app; 

    public static void Initialize(RenderWindow app) 
    { 
    monitoredObjects = new List(); 

    } 

    public static void Watch(object o) 
    { 
    monitoredObjects.Add(o); 
    o.PropertyChanged += new EventHandler(monitor_PropertyChanged); 
    } 

    public static void Unwatch(object o) 
    { 
    o.PropertyChanged -= new EventHandler(monitor_PropertyChanged); 
    monitoredObjects.Remove(o); 
    } 

    public static monitor_PropertyChanged(object sender, PropertyChangedEventArgs e){ 
    // Not actual code, I actually draw this in game 
    Console.WriteLine(e.SomeValue); 
    } 

    public static void Draw(RenderWindow app) 
    { 
        //Not actual code, I actually draw this in game 
    foreach (object o in monitoredObjects) 
    Console.WriteLine(o.ToString()); 
    } 
} 

public class Property 
{ 
    private object obj; 
    private PropertyInfo propertyInfo; 

    public object PropObj{ 
    get{ return this.obj; } 
    } 

    public override string ToString() 
    { 
    return propertyInfo.Name + ": " + propertyInfo.GetValue(obj, null).ToString(); 
    } 

    public Property(object o, string property) 
    { 
    obj = o; 
    propertyInfo = o.GetType().GetProperty(property); 
    } 
} 

希望這有助於 最好的問候, 湯姆。