Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 8 additions & 165 deletions System/Windows/Forms/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,175 +4,18 @@

namespace System.Windows.Forms
{
internal class Command : WeakReference
internal class Command : IDisposable
{
private static Command[] cmds;
private static readonly Type CommandType = typeof(Control).Assembly.GetType(typeof(Command).FullName);
private static readonly Reflection.PropertyInfo CommandIDProperty = CommandType.GetProperty(nameof(ID), typeof(Int32));
private static readonly Reflection.MethodInfo CommandDisposeMethod = CommandType.GetMethod(nameof(Dispose), Type.EmptyTypes);

private static int icmdTry;
private readonly Object cmd;

private static object internalSyncObject = new object();
public Command(ICommandExecutor target) => this.cmd = Activator.CreateInstance(CommandType, target);

private const int idMin = 256;
public Int32 ID => (Int32)CommandIDProperty.GetValue(this.cmd);

private const int idLim = 65536;

internal int id;

public virtual int ID => id;

public Command(ICommandExecutor target)
: base(target, trackResurrection: false)
{
AssignID(this);
}

protected static void AssignID(Command cmd)
{
lock (internalSyncObject)
{
int num;
if (cmds == null)
{
cmds = new Command[20];
num = 0;
}
else
{
int num2 = cmds.Length;
if (icmdTry >= num2)
{
icmdTry = 0;
}
num = icmdTry;
while (true)
{
if (num < num2)
{
if (cmds[num] == null)
{
break;
}
num++;
continue;
}
num = 0;
while (true)
{
if (num < icmdTry)
{
if (cmds[num] == null)
{
break;
}
num++;
continue;
}
num = 0;
while (true)
{
if (num < num2)
{
if (cmds[num].Target == null)
{
break;
}
num++;
continue;
}
num = cmds.Length;
num2 = Math.Min(65280, 2 * num);
if (num2 <= num)
{
GC.Collect();
num = 0;
while (true)
{
if (num < num2)
{
if (cmds[num] == null || cmds[num].Target == null)
{
break;
}
num++;
continue;
}
throw new ArgumentException("CommandIdNotAllocated");
}
}
else
{
Command[] destinationArray = new Command[num2];
Array.Copy(cmds, 0, destinationArray, 0, num);
cmds = destinationArray;
}
break;
}
break;
}
break;
}
}
cmd.id = num + 256;
cmds[num] = cmd;
icmdTry = num + 1;
}
}

public static bool DispatchID(int id)
{
return GetCommandFromID(id)?.Invoke() ?? false;
}

protected static void Dispose(Command cmd)
{
lock (internalSyncObject)
{
if (cmd.id >= 256)
{
cmd.Target = null;
if (cmds[cmd.id - 256] == cmd)
{
cmds[cmd.id - 256] = null;
}
cmd.id = 0;
}
}
}

public virtual void Dispose()
{
if (id >= 256)
{
Dispose(this);
}
}

public static Command GetCommandFromID(int id)
{
lock (internalSyncObject)
{
if (cmds == null)
{
return null;
}
int num = id - 256;
if (num < 0 || num >= cmds.Length)
{
return null;
}
return cmds[num];
}
}

public virtual bool Invoke()
{
object target = Target;
if (!(target is ICommandExecutor))
{
return false;
}
((ICommandExecutor)target).Execute();
return true;
}
public void Dispose() => CommandDisposeMethod.Invoke(this.cmd, null);
}
}