/// DebugOverrule.cs Copyright (c) 2010 Tony Tanzillo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
/// This sample was written to help demonstrate
/// the potential overhead associated with the use
/// of Overrules, namely the ObjectOverrule, whose
/// methods have the highest call frequency of all
/// of Overrule types.
///
/// Compile and load this code, and then issue the
/// DEBUGOVER command to create an ObjectOverrule
/// that counts the number of calls to its Open()
/// and Close() overrides. Note that every virtual
/// method of an ObjectOverrule is called even if
/// it is not overridden in a concrete derived type,
/// and calls to all of those virtual methods aren't
/// being counted by this sample. The sample only
/// counts the number of calls that are made to its
/// Open() and Close() overrides.
///
/// The current number of calls that have been made
/// to the Overrule's Open() and Close() methods are
/// shown in the AutoCAD status bar, and updated on
/// each Idle notification.
///
/// The Trace option displays each call to Close()
/// on the AutoCAD console (careful, as this will
/// flood the console if left on for any length of
/// time). The Reset option resets the call count.
///
/// After issuing DEBUGOVER, notice that little more
/// than moving the mouse pointer results in calls to
/// the Open() and Close() methods. Try doing routine
/// AutoCAD editing and notice the number of calls to
/// Open() and Close() as a result.
///
/// Try using the AutoCAD MOVE command on a few dozen
/// objects, and while dragging the selected objects,
/// note the number of calls to Open() and Close() that
/// result.
///
/// What you observe should help to make it clear that
/// while ObjectOverrule is a powerful abstraction that
/// can be used to solve a broad range of problems, if
/// not implemented correctly, it can adversely impact
/// the performance of virtually everything a user does
/// with AutoCAD.
namespace Autodesk.AutoCAD.DatabaseServices.MyExtensions
{
public class DebugOverruleCommands
{
[CommandMethod( "DEBUGOVER" )]
public static void DebugOverruleCommand()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if( !DebugOverrule.IsAlive )
{
var instance = DebugOverrule.Instance;
doc.Editor.WriteMessage( "\nDebugOverrule enabled" );
return;
}
PromptKeywordOptions pko
= new PromptKeywordOptions
( "" ); pko.Keywords.Add( "Reset" );
pko.Keywords.Add( "Dispose" );
pko.Keywords.Add( "Trace" );
pko.Keywords.Add( "eXit" );
pko.Keywords.Default = "eXit";
pko.Message = string.Format( "\nCall count: {0}, ",
DebugOverrule.Instance.Count );
PromptResult result = doc.Editor.GetKeywords( pko );
if( result.Status != PromptStatus.OK )
return;
switch( result.StringResult )
{
case "Reset":
DebugOverrule.Instance.Reset();
break;
case "Dispose":
DebugOverrule.Instance.Dispose();
break;
case "Trace":
DebugOverrule.Instance.Trace ^= true;
break;
default:
break;
}
}
}
static class MyUtils
{
public static void WriteLine( string fmt, params object[] args )
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if( doc != null )
{
if( !fmt.StartsWith( "\n" ) )
doc.Editor.WriteMessage( "\n" + fmt, args );
else
doc.Editor.WriteMessage( fmt, args );
}
}
}
class DebugOverrule : ObjectOverrule
{
static RXClass rxclass
= RXClass
.GetClass( typeof( DBObject
) ); bool disposed = false;
Windows.Pane pane = null;
bool trace = false;
long count = 0;
DebugOverrule()
{
Overrule.AddOverrule( rxclass, this, true );
Application.Idle += idle;
pane
= new Windows
.Pane(); pane.Style = Windows.PaneStyles.Normal;
Application.StatusBar.Panes.Insert( 1, pane );
}
public override void Open( DBObject dbObject, OpenMode mode )
{
++count;
base.Open( dbObject, mode );
}
public override void Close( DBObject dbObject )
{
++count;
if( trace )
MyUtils.WriteLine( "DebugOverrule.Close({0})\n",
dbObject.Handle.ToString() );
base.Close( dbObject );
}
public bool Trace
{
get
{
return trace;
}
set
{
trace = value;
}
}
void idle( object sender, EventArgs e )
{
this.pane.Text = string.Format( "DebugOverrule.Count = {0}", count );
Application.StatusBar.Update();
}
public void Reset()
{
count = 0L;
}
public long Count
{
get
{
return count;
}
}
static DebugOverrule()
{
Application.QuitWillStart += quitWillStart;
}
static void quitWillStart( object sender, EventArgs e )
{
if( instance != null )
{
instance.Dispose();
instance = null;
}
}
static DebugOverrule instance = null;
internal static DebugOverrule Instance
{
get
{
if( instance == null )
instance
= new DebugOverrule
(); return instance;
}
}
internal static bool IsAlive
{
get
{
return instance != null;
}
}
protected override void Dispose( bool disposing )
{
if( disposing && !disposed )
{
Application.Idle -= idle;
Application.StatusBar.Panes.Remove( this.pane );
disposed = true;
Overrule.RemoveOverrule( rxclass, this );
if( instance == this )
instance = null;
}
base.Dispose( disposing );
}
}
}