完善物业监控代码?

发布于 2024-08-21 13:15:59 字数 1351 浏览 4 评论 0原文

我在我正在开发的 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# 中的值类型,我不知道该怎么做。也许使用闭包和 lambda 表达式?早些时候有人建议我这样做,但我不知道该怎么做。还有其他方法可以改善这一点吗?

谢谢

I made a utility debug class in a C# game I'm working on to be able to monitor and watch values of properties. Goes like this:

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

Now in order to monitor a property, say my game's FPS, I must do

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

Wouldn't there be a way to somehow make this simpler to use? Ideally I'd like to be able to do

Monitor.Watch(Game.FPS);

But since we can't store pointers to value types in C#, I don't know how I would do this. Maybe using closures and lambada expressions? I was suggested this earlier but I'm not sure how to do it. Any other ways to improve this?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风铃鹿 2024-08-28 13:15:59

就我个人而言,我要做的是重新设计您的 Monitor 类以接受 Func 作为输入,并返回可用于“取消监视”该类的监视句柄。

通过这样做,您将能够编写:

 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”工作,因为您需要有某种方法来删除委托,您可能希望匿名定义该委托(就像我上面所做的那样)。

Personally, what I would do is rework your Monitor class to accept a Func<string> as input, and return a monitoring handle that could be used to "unmonitor" the class.

By doing that, you'd be able to write:

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

This could look something like:

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

You'd need to implement some interface for the handle - but this really could be anything, since it's just an object used as a hash table lookup for allowing unsubscription. You only need this to allow "Unwatch" to work, since you need to have some way to remove the delegate, which you'll probably want to define anonymously (as I did above).

伊面 2024-08-28 13:15:59

为什么你不使用 INotifyPropertyChanged 界面并直接启动Monitor 类中的事件,类似这样...假设您的对象实现了接口...并且对象中的每个属性都会引发一个“PropertyChanged”事件,其中参数指示值...这样,它将是一个即发即忘的解决方案,而不是循环遍历列表...当您使用用作“初始化”参数的“渲染窗口”来调用实例化“监视器”时。另请注意,“Property”类略有修改,以包含一个 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);
  }
 }

希望这有帮助,
此致,
汤姆.

Why are you not using INotifyPropertyChanged interface and just fire off the events within the Monitor class, something like this...assume your objects implement the interface...and every property in your objects raise a 'PropertyChanged' event with parameters indicating the values...in that way, it will be a fire and forget solution instead of looping through the list... as you call instantiate 'Monitor' with a 'RenderWindow' used as parameter to 'Initialize'. Also notice that 'Property' class is slightly modified to include a get accessor to return the object in question...

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,
Best regards,
Tom.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文