Posted 20 years ago
by Ashton
-
Developer,
Schema Solutions LLC
In testing the SE3.0 release, I need to serialize a macro (I want to save macros so they can be used in subsequent app executions). Since EditCommand and all subclasses are not serializable, I created the following classes to handle serializing MacroCommand. I have tested it and it works fairly well. It will not serialize Paste commands but should handle everything else. It also uses some heavy reflection so CAS might be an issue for some users.
Here is a sample on how to call this:// Here are the class definitions
If anyone has any improvements or implements the Paste command, please repost.
Thanks,
Ashton
[Modified at 04/27/2005 06:48 AM]
Here is a sample on how to call this:
// serialize a macro that was just run
PersistentMacro mymacro = new PersistentMacro(editor.MacroRecording.LastMacroCommand);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binfm = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
// serialize the macro we created
binfm.Serialize(File.Create(@"c:\test.macro"), mymacro);
...
// deserialize
PersistentMacro newmymacro = (PersistentMacro)binfm.Deserialize(File.Open(@"c:\test.macro", FileMode.Open));
MacroCommand mm = newmymacro.GetMacro();
editor.SelectedView.RaiseEditCommand(mm);
[Serializable]
public class PersistentMacro : ISerializable
{
private ArrayList m_CmdList = new ArrayList();
/// <summary>
/// Loop through the list and recreate the commands needed by SyntaxEditor
/// </summary>
/// <returns></returns>
public MacroCommand GetMacro ()
{
// local variables
Assembly ass = Assembly.GetAssembly(typeof(EditCommand));
ArrayList cmdList = new ArrayList();
EditCommand cmd;
// loop through the list of persistent items we have
foreach (PersistentMacroCommand macro in this.m_CmdList)
{
// create the item based on type of command we have
if (macro is PersistentTypingMacroCommand)
{
PersistentTypingMacroCommand typingMacro = macro as PersistentTypingMacroCommand;
cmd = (EditCommand)ass.CreateInstance(
macro.CommandName, true, BindingFlags.CreateInstance, null,
new object[] {typingMacro.Charactere, typingMacro.Overwrite}, null, null);
}
else if (macro is PersistentCasingMacroCommand)
{
PersistentCasingMacroCommand caseMacro = macro as PersistentCasingMacroCommand;
cmd = (EditCommand)ass.CreateInstance(
macro.CommandName, true, BindingFlags.CreateInstance, null,
new object[] {Enum.Parse(typeof(CharacterCasing), caseMacro.EnumValue)}, null, null);
}
else if (macro is PersistentCommentMacroCommand)
{
PersistentCommentMacroCommand commentMacro = macro as PersistentCommentMacroCommand;
cmd = (EditCommand)ass.CreateInstance(
macro.CommandName, true, BindingFlags.CreateInstance, null,
new object[] {commentMacro.Prefix}, null, null);
}
else
{
cmd = (EditCommand)ass.CreateInstance(
macro.CommandName, true, BindingFlags.CreateInstance, null,
null, null, null);
}
// add the item to the list
cmdList.Add(cmd);
}
// create a macro command using the list we created
MacroCommand newMacro = new MacroCommand(cmdList);
return newMacro;
}
/// <summary>
/// Called by ISerialization to reload items into the class during deser
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
protected PersistentMacro (SerializationInfo info, StreamingContext context)
{
this.m_CmdList = info.GetValue("MacroCommand", typeof(ArrayList)) as ArrayList;
}
/// <summary>
/// Ctor to serialize the objects manually
/// </summary>
/// <param name="command"></param>
public PersistentMacro (MacroCommand command)
{
// parse the command
this.ParseCommand(command);
}
/// <summary>
/// Loop through the commands and serialize them out to an array list
/// </summary>
/// <param name="command"></param>
private void ParseCommand (MacroCommand command)
{
// local variables
Type type;
PersistentMacroCommand macro;
// loop through the command in the command
foreach (EditCommand cmd in command)
{
// get the type of the cmd
type = cmd.GetType();
if (cmd is TypingCommand)
macro = HandleCommand(cmd as TypingCommand, type); /* handle when user simply types a key */
else if (cmd is MacroCommand || cmd is PasteFromClipboardCommand)
continue; /* skip this because we can't serialize these easily */
else if (cmd is CommentLinesCommand)
macro = HandleCommand(cmd as CommentLinesCommand, type);/* serialize uncomment command */
else if (cmd is UncommentLinesCommand)
macro = HandleCommand(cmd as UncommentLinesCommand, type);/* serialize comment command */
else if (cmd is ChangeCharacterCasingCommand)
macro = HandleCommand(cmd as ChangeCharacterCasingCommand, type);/* serialize change char casing which takes an enum value */
else
macro = HandleCommand(type); /* handle the basic edit command that has no private fields */
this.m_CmdList.Add(macro);
}
}
/// <summary>
/// Handle the base type of command
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
private PersistentMacroCommand HandleCommand (Type type)
{
// local variables
PersistentMacroCommand macro = new PersistentMacroCommand(type.FullName);
return macro;
}
/// <summary>
/// Handle character casing command which have an enum in private member
/// </summary>
/// <param name="command"></param>
/// <param name="type"></param>
/// <returns></returns>
private PersistentMacroCommand HandleCommand (ChangeCharacterCasingCommand command, Type type)
{
// local variables
PersistentCasingMacroCommand macro;
string enumvalue = "";
// get the field info items from the type
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.FieldType == typeof(System.Enum))
enumvalue = field.GetValue(command).ToString();
}
// create the macro object
macro = new PersistentCasingMacroCommand(type.FullName, enumvalue);
return macro;
}
/// <summary>
/// Handle uncomment commands which have a prefix private member
/// </summary>
/// <param name="command"></param>
/// <param name="type"></param>
/// <returns></returns>
private PersistentMacroCommand HandleCommand (UncommentLinesCommand command, Type type)
{
// local variables
PersistentCommentMacroCommand macro;
string prefix = "--";
// get the field info items from the type
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.FieldType == typeof(System.String))
prefix = field.GetValue(command).ToString();
}
// create the macro object
macro = new PersistentCommentMacroCommand(type.FullName, prefix);
return macro;
}
/// <summary>
/// Handle comment lines which have a prefix private member
/// </summary>
/// <param name="command"></param>
/// <param name="type"></param>
/// <returns></returns>
private PersistentMacroCommand HandleCommand (CommentLinesCommand command, Type type)
{
// local variables
PersistentCommentMacroCommand macro;
string prefix = "--";
// get the field info items from the type
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.FieldType == typeof(System.String))
prefix = field.GetValue(command).ToString();
}
// create the macro object
macro = new PersistentCommentMacroCommand(type.FullName, prefix);
return macro;
}
/// <summary>
/// Handle typing commands which have char and bool private members
/// </summary>
/// <param name="command"></param>
/// <param name="type"></param>
/// <returns></returns>
private PersistentMacroCommand HandleCommand (TypingCommand command, Type type)
{
// local variables
PersistentTypingMacroCommand macro;
char cChar = (char)0;
bool bOverwrite = false;
// get the field info items from the type
FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.FieldType == typeof(System.Char))
cChar = (char)field.GetValue(command);
else if (field.FieldType == typeof(System.Boolean))
bOverwrite = (bool)field.GetValue(command);
}
// create the macro object
macro = new PersistentTypingMacroCommand(type.FullName, cChar, bOverwrite);
return macro;
}
/// <summary>
/// Serialize the array list
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("MacroCommand", this.m_CmdList);
}
}
[Serializable]
public class PersistentMacroCommand
{
private string m_sCommandName;
public PersistentMacroCommand (string commandName) {this.m_sCommandName = commandName;}
public string CommandName {get {return this.m_sCommandName;}}
}
[Serializable]
public class PersistentTypingMacroCommand : PersistentMacroCommand
{
private char m_cChar;
private bool m_bOverwrite;
public PersistentTypingMacroCommand (string commandName, char character, bool overwrite) : base(commandName)
{this.m_cChar = character; this.m_bOverwrite = overwrite;}
public char Charactere {get {return this.m_cChar;}}
public bool Overwrite {get {return this.m_bOverwrite;}}
}
[Serializable]
public class PersistentCommentMacroCommand : PersistentMacroCommand
{
private string m_sPrefix;
public PersistentCommentMacroCommand (string commandName, string prefix) : base(commandName)
{this.m_sPrefix = prefix;}
public string Prefix {get {return this.m_sPrefix;}}
}
[Serializable]
public class PersistentCasingMacroCommand : PersistentMacroCommand
{
private string m_sEnum;
public PersistentCasingMacroCommand (string commandName, string enumValue) : base(commandName)
{this.m_sEnum = enumValue;}
public string EnumValue {get {return this.m_sEnum;}}
}
// This code is release under the "I RULE" License
// You may use this code provide you admit I rule if
// you ever meet me in person :)
Thanks,
Ashton
[Modified at 04/27/2005 06:48 AM]