2010-02-13 80 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); 
    } 
} 

希望这有助于 最好的问候, 汤姆。