2010-02-13 6 views
5

Utworzyłem klasę debugowania narzędzi w grze C#, nad którą pracuję, aby móc monitorować i oglądać wartości właściwości. Idzie tak:Ulepsz kod monitorowania właściwości?

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

Teraz w celu monitorowania właściwość, że mój grze FPS, muszę zrobić

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

nie Czy istnieje jakiś sposób, aby uczynić to prostsze w użyciu? Idealnie chciałabym móc zrobić

Monitor.Watch(Game.FPS); 

Ale ponieważ nie możemy store pointers to value types w C#, nie wiem w jaki sposób to zrobić. Może przy użyciu zamknięć i wyrażeń lambada? Zasugerowałem to wcześniej, ale nie jestem pewien, jak to zrobić. Jakieś inne sposoby na poprawę tego?

Dzięki

Odpowiedz

5

Osobiście, co chciałbym zrobić, to przerobienie swoją klasę monitora zaakceptować Func<string> jako wejście i zwraca uchwyt do monitorowania, które mogłyby być wykorzystane do „unmonitor” klasa.

Dzięki temu, że byłbyś w stanie napisać:

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

Może to wyglądać mniej więcej tak:

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

trzeba by wdrożyć jakiś interfejs do rączki - ale to naprawdę może być cokolwiek, ponieważ jest to po prostu obiekt używany jako tablica hash do zezwalania na rezygnację z subskrypcji. Potrzebujesz tego tylko, aby "Unwatch" działał, ponieważ musisz mieć jakiś sposób na usunięcie delegata, który prawdopodobnie będziesz chciał zdefiniować anonimowo (tak jak to zrobiłem powyżej).

1

Dlaczego nie używasz interfejsu INotifyPropertyChanged i po prostu odpalasz zdarzenia w klasie Monitor, coś w tym stylu ... zakładaj, że twoje obiekty implementują interfejs ... i każda właściwość w twoich obiektach wywołuje zdarzenie "PropertyChanged" z parametry wskazujące wartości ... w ten sposób, będzie to rozwiązanie przeciwpożarowe i zapomnij zamiast pętli przez listę ... jak wywołasz instancję "Monitoruj" z "RenderWindow" używanym jako parametr "Inicjalizuj". Również zauważyć, że „mienie” klasa jest nieco zmodyfikowany, aby zawierać akcesor dostać się do zwrotu danego przedmiotu ...

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

nadzieję, że to pomoże, poważaniem, Tom.