Author Topic: C# Code Snippets  (Read 1690 times)

0 Members and 1 Guest are viewing this topic.

Offline MyndFyre

  • Boticulator Extraordinaire
  • x86
  • Hero Member
  • *****
  • Posts: 4540
  • The wait is over.
    • View Profile
    • JinxBot :: the evolution in boticulation
C# Code Snippets
« on: June 19, 2008, 04:16:32 pm »
I was telling Warrior about a new code snippet I made recently for use in JinxBot:

Code: [Select]
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>JinxBot Event</Title>
<Shortcut>jbevent</Shortcut>
<Description>Code snippet for declaring a JinxBot event.</Description>
<Author>MyndFyre</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>eventName</ID>
<ToolTip>The name of the event.</ToolTip>
<Default>EventName</Default>
</Literal>
<Literal>
<ID>eventtype</ID>
<ToolTip>The type name component for the delegate and event arguments used by this event.  For example,
you might enter "EnteredChat" for EnteredChatEventHandler and EnteredChatEventArgs.</ToolTip>
<Default>EventType</Default>
</Literal>
<Literal>
<ID>eventdesc</ID>
<ToolTip>The comment to include.</ToolTip>
<Default>CommentText</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[#region $eventName$ event
[NonSerialized]
private Dictionary<Priority, List<$eventtype$EventHandler>> __$eventName$ = new Dictionary<Priority, List<$eventtype$EventHandler>>(3);
/// <summary>
    /// Informs listeners $eventdesc$
/// </summary>
/// <remarks>
/// <para>Registering for this event with this member will register with <see cref="Priority">Normal priority</see>.  To register for
/// <see cref="Priority">High</see> or <see cref="Priority">Low</see> priority, use the <see>Register$eventName$Notification</see> and
/// <see>Unregister$eventName$Notification</see> methods.</para>
/// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
/// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
/// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
/// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
/// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
/// </remarks>
        public event $eventtype$EventHandler $eventName$
{
add
{
lock (__$eventName$)
{
if (!__$eventName$.ContainsKey(Priority.Normal))
{
__$rvrntName$.Add(Priority.Normal, new List<$eventtype$EventHandler>());
}
}
__$eventName$[Priority.Normal].Add(value);
}
remove
{
if (__$eventName$.ContainsKey(Priority.Normal))
{
__$eventName$[Priority.Normal].Remove(value);
}
}
}

/// <summary>
/// Registers for notification of the <see>$eventName$</see> event at the specified priority.
/// </summary>
/// <remarks>
/// <para>The event system in the JinxBot API supports normal event registration and prioritized event registration.  You can use
/// normal syntax to register for events at <see cref="Priority">Normal priority</see>, so no special registration is needed; this is
/// accessed through normal event handling syntax (the += syntax in C#, or the <see langword="Handles" lang="VB" /> in Visual Basic.</para>
/// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
/// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
/// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
/// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
/// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
/// <para>To be well-behaved within JinxBot, plugins should always unregister themselves when they are being unloaded or when they
/// otherwise need to do so.  Plugins may opt-in to a Reflection-based event handling registration system which uses attributes to
/// mark methods that should be used as event handlers.</para>
/// </remarks>
/// <seealso cref="$eventName$" />
/// <seealso cref="Unregister$eventName$Notification" />
public void Register$eventName$Notification(Priority p, $eventtype$EventHandler callback)
{
lock (__$eventName$)
{
if (!__$eventName$.ContainsKey(p))
{
__$rvrntName$.Add(p, new List<$eventtype$EventHandler>());
}
}
__$eventName$[p].Add(value);
}

/// <summary>
/// Unregisters for notification of the <see>$eventName$</see> event at the specified priority.
/// </summary>
/// <remarks>
/// <para>The event system in the JinxBot API supports normal event registration and prioritized event registration.  You can use
/// normal syntax to register for events at <see cref="Priority">Normal priority</see>, so no special registration is needed; this is
/// accessed through normal event handling syntax (the += syntax in C#, or the <see langword="Handles" lang="VB" /> in Visual Basic.</para>
/// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
/// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
/// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
/// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
/// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
/// <para>To be well-behaved within JinxBot, plugins should always unregister themselves when they are being unloaded or when they
/// otherwise need to do so.  Plugins may opt-in to a Reflection-based event handling registration system which uses attributes to
/// mark methods that should be used as event handlers.</para>
/// </remarks>
/// <seealso cref="$eventName$" />
/// <seealso cref="Register$eventName$Notification" />
public void Unregister$eventName$Notification(Priority p, $eventtype$EventHandler callback)
{
if (__$eventName$.ContainsKey(Priority.Normal))
{
__$eventName$[Priority.Normal].Remove(value);
}
}

/// <summary>
/// Raises the $eventName$ event.
/// </summary>
/// <remarks>
/// <para>Only high-priority events are invoked immediately; others are deferred.  For more information, see <see>$eventName$</see>.</para>
/// </remarks>
/// <seealso cref="$eventName$" />
protected virtual void On$eventName$($eventtype$EventArgs e)
{
foreach ($eventtype$EventHandler eh in __$eventName$[Priority.High])
{
try
{
eh(this, e);
}
catch (Exception ex)
{
ReportException(
ex,
new KeyValuePair<string, object>("delegate", eh),
new KeyValuePair<string, object>("Event", "$eventName$"),
new KeyValuePair<string, object>("param: priority", Priority.High),
new KeyValuePair<string, object>("param: this", this),
new KeyValuePair<string, object>("param: e", e)
);
}
}

ThreadPool.QueueUserWorkItem((WaitCallback)delegate
{
foreach ($eventtype$EventHandler eh in __$eventName$[Priority.Normal])
{
try
{
eh(this, e);
}
catch (Exception ex)
{
ReportException(
ex,
new KeyValuePair<string, object>("delegate", eh),
new KeyValuePair<string, object>("Event", "$eventName$"),
new KeyValuePair<string, object>("param: priority", Priority.Normal),
new KeyValuePair<string, object>("param: this", this),
new KeyValuePair<string, object>("param: e", e)
);
}
}
ThreadPool.QueueUserWorkItem((WaitCallback)delegate
{
foreach ($eventtype$EventHandler eh in __$eventName$[Priority.Low])
{
try
{
eh(this, e);
}
catch (Exception ex)
{
ReportException(
ex,
new KeyValuePair<string, object>("delegate", eh),
new KeyValuePair<string, object>("Event", "$eventName$"),
new KeyValuePair<string, object>("param: priority", Priority.Low),
new KeyValuePair<string, object>("param: this", this),
new KeyValuePair<string, object>("param: e", e)
);
}
}
});
});
}
#endregion
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>

Pretty slick, it supports my prioritized event subsystem.  To access it, I type "jbevent" and press tab.  This is what I got after filling in only three fields:

Code: [Select]
        #region UserSpoke event
        [NonSerialized]
        private Dictionary<Priority, List<ChatEventHandler>> __UserSpoke = new Dictionary<Priority, List<ChatEventHandler>>(3);
        /// <summary>
        /// Informs listeners that a user in the channel has said something.
        /// </summary>
        /// <remarks>
        /// <para>Registering for this event with this member will register with <see cref="Priority">Normal priority</see>.  To register for
        /// <see cref="Priority">High</see> or <see cref="Priority">Low</see> priority, use the <see>RegisterUserSpokeNotification</see> and
        /// <see>UnregisterUserSpokeNotification</see> methods.</para>
        /// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
        /// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
        /// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
        /// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
        /// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
        /// </remarks>
        public event ChatEventHandler UserSpoke
        {
            add
            {
                lock (__UserSpoke)
                {
                    if (!__UserSpoke.ContainsKey(Priority.Normal))
                    {
                        __.Add(Priority.Normal, new List<ChatEventHandler>());
                    }
                }
                __UserSpoke[Priority.Normal].Add(value);
            }
            remove
            {
                if (__UserSpoke.ContainsKey(Priority.Normal))
                {
                    __UserSpoke[Priority.Normal].Remove(value);
                }
            }
        }

        /// <summary>
        /// Registers for notification of the <see>UserSpoke</see> event at the specified priority.
        /// </summary>
        /// <remarks>
        /// <para>The event system in the JinxBot API supports normal event registration and prioritized event registration.  You can use
        /// normal syntax to register for events at <see cref="Priority">Normal priority</see>, so no special registration is needed; this is
        /// accessed through normal event handling syntax (the += syntax in C#, or the <see langword="Handles" lang="VB" /> in Visual Basic.</para>
        /// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
        /// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
        /// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
        /// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
        /// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
        /// <para>To be well-behaved within JinxBot, plugins should always unregister themselves when they are being unloaded or when they
        /// otherwise need to do so.  Plugins may opt-in to a Reflection-based event handling registration system which uses attributes to
        /// mark methods that should be used as event handlers.</para>
        /// </remarks>
        /// <seealso cref="UserSpoke" />
        /// <seealso cref="UnregisterUserSpokeNotification" />
        public void RegisterUserSpokeNotification(Priority p, ChatEventHandler callback)
        {
            lock (__UserSpoke)
            {
                if (!__UserSpoke.ContainsKey(p))
                {
                    __.Add(p, new List<ChatEventHandler>());
                }
            }
            __UserSpoke[p].Add(value);
        }

        /// <summary>
        /// Unregisters for notification of the <see>UserSpoke</see> event at the specified priority.
        /// </summary>
        /// <remarks>
        /// <para>The event system in the JinxBot API supports normal event registration and prioritized event registration.  You can use
        /// normal syntax to register for events at <see cref="Priority">Normal priority</see>, so no special registration is needed; this is
        /// accessed through normal event handling syntax (the += syntax in C#, or the <see langword="Handles" lang="VB" /> in Visual Basic.</para>
        /// <para>Events in the JinxBot API are never guaranteed to be executed on the UI thread.  Events that affect the user interface should
        /// be marshaled back to the UI thread by the event handling code.  Generally, high-priority event handlers are
        /// raised on the thread that is parsing data from Battle.net, and lower-priority event handler are executed from the thread pool.</para>
        /// <para>JinxBot guarantees that all event handlers will be fired regardless of exceptions raised in previous event handlers.  However,
        /// if a plugin repeatedly raises an exception, it may be forcefully unregistered from events.</para>
        /// <para>To be well-behaved within JinxBot, plugins should always unregister themselves when they are being unloaded or when they
        /// otherwise need to do so.  Plugins may opt-in to a Reflection-based event handling registration system which uses attributes to
        /// mark methods that should be used as event handlers.</para>
        /// </remarks>
        /// <seealso cref="UserSpoke" />
        /// <seealso cref="RegisterUserSpokeNotification" />
        public void UnregisterUserSpokeNotification(Priority p, ChatEventHandler callback)
        {
            if (__UserSpoke.ContainsKey(Priority.Normal))
            {
                __UserSpoke[Priority.Normal].Remove(value);
            }
        }

        /// <summary>
        /// Raises the UserSpoke event.
        /// </summary>
        /// <remarks>
        /// <para>Only high-priority events are invoked immediately; others are deferred.  For more information, see <see>UserSpoke</see>.</para>
        /// </remarks>
        /// <seealso cref="UserSpoke" />
        protected virtual void OnUserSpoke(ChatEventArgs e)
        {
            foreach (ChatEventHandler eh in __UserSpoke[Priority.High])
            {
                try
                {
                    eh(this, e);
                }
                catch (Exception ex)
                {
                    ReportException(
                        ex,
                        new KeyValuePair<string, object>("delegate", eh),
                        new KeyValuePair<string, object>("Event", "UserSpoke"),
                        new KeyValuePair<string, object>("param: priority", Priority.High),
                        new KeyValuePair<string, object>("param: this", this),
                        new KeyValuePair<string, object>("param: e", e)
                        );
                }
            }

            ThreadPool.QueueUserWorkItem((WaitCallback)delegate
            {
                foreach (ChatEventHandler eh in __UserSpoke[Priority.Normal])
                {
                    try
                    {
                        eh(this, e);
                    }
                    catch (Exception ex)
                    {
                        ReportException(
                            ex,
                            new KeyValuePair<string, object>("delegate", eh),
                            new KeyValuePair<string, object>("Event", "UserSpoke"),
                            new KeyValuePair<string, object>("param: priority", Priority.Normal),
                            new KeyValuePair<string, object>("param: this", this),
                            new KeyValuePair<string, object>("param: e", e)
                            );
                    }
                }
                ThreadPool.QueueUserWorkItem((WaitCallback)delegate
                {
                    foreach (ChatEventHandler eh in __UserSpoke[Priority.Low])
                    {
                        try
                        {
                            eh(this, e);
                        }
                        catch (Exception ex)
                        {
                            ReportException(
                                ex,
                                new KeyValuePair<string, object>("delegate", eh),
                                new KeyValuePair<string, object>("Event", "UserSpoke"),
                                new KeyValuePair<string, object>("param: priority", Priority.Low),
                                new KeyValuePair<string, object>("param: this", this),
                                new KeyValuePair<string, object>("param: e", e)
                                );
                        }
                    }
                });
            });
        }
        #endregion


Primary drawback is that they don't work like macros.  I have to re-create all my events if this changes.  Sad day.
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Our species really annoys me.