2010-02-13 30 views
5

Tôi đã tạo một lớp gỡ lỗi tiện ích trong trò chơi C# mà tôi đang làm việc để có thể theo dõi và xem các giá trị của thuộc tính. Đi như thế này:Cải thiện mã theo dõi tài sản?

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); 
    } 
} 

Bây giờ để theo dõi tài sản, nói trò chơi của tôi FPS, tôi phải làm gì

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

Sẽ không có một cách nào đó làm cho điều này đơn giản để sử dụng không? Lý tưởng nhất tôi muốn có thể làm

Monitor.Watch(Game.FPS); 

Nhưng vì chúng tôi không thể store pointers to value types trong C#, tôi không biết làm cách nào để thực hiện việc này. Có thể sử dụng bao đóng và biểu thức lambada? Tôi đã đề xuất điều này sớm hơn nhưng tôi không chắc chắn làm thế nào để làm điều đó. Bất kỳ cách nào khác để cải thiện điều này?

Cảm ơn

Trả lời

5

Cá nhân, những gì tôi sẽ làm là làm lại lớp Monitor của bạn để chấp nhận một Func<string> như đầu vào, và trả về một xử lý giám sát có thể được sử dụng để "unmonitor" lớp.

Bằng cách đó, bạn sẽ có thể viết:

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

Điều này có thể giống như thế:

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... 
    } 
} 

Bạn sẽ cần phải thực hiện một số giao diện cho xử lý - nhưng điều này thực sự có thể là bất cứ điều gì, vì nó chỉ là một đối tượng được sử dụng như một tra cứu bảng băm cho phép hủy đăng ký. Bạn chỉ cần điều này để cho phép "Unwatch" hoạt động, vì bạn cần phải có một số cách để xóa đại biểu mà bạn có thể muốn xác định ẩn danh (như tôi đã làm ở trên).

1

Tại sao bạn không sử dụng giao diện INotifyPropertyChanged và chỉ tắt các sự kiện trong lớp Monitor các tham số chỉ ra các giá trị ... theo cách đó, nó sẽ là một giải pháp lửa và quên thay vì lặp qua danh sách ... khi bạn gọi instantiate 'Monitor' với một 'RenderWindow' được sử dụng làm tham số thành 'Initialize'. Cũng cần lưu ý rằng 'tài sản' lớp được chút thay đổi để bao gồm một get accessor để trả lại đối tượng trong câu hỏi ...

 
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); 
    } 
} 

Hope this helps, Trân trọng, Tom.

Các vấn đề liên quan