Generics - delegate and custom event args

When you want to create custom events, often you need to pass an event argument, and as often you need only to pass in one parameter - your object. So what you used to do is:

public event MyCustomEventHandler MyCustomEvent;
public delegate void MyCustomEventHandler(MyCustomEventArg evt);
public class MyObject
{
public string foo;
public int count;
public DateTime when;
public MyObject()
{
foo = "hello world";
count = 42;
when = DateTime.Now;
}
public override string ToString()
{
return string.Format("{0}\t{1}\t{2}",foo,count,when);
}
}
public class MyCustomEventArg : EventArgs
{
private MyObject _value;
public MyObject Data
{
get { return _value; }
set { _value = value; }
}
public MyCustomEventArg(MyObject value)
{
_value = value;
}
}

The not so pretty thing about it is that you had to mind-numbingly create a class which derives from EventArgs just to be able to pass your single event argument MyObject .

Now come generics and Microsoft has provided the generic type: EventHandler<TEventArgs> and with it, you can now code

public event EventHandler<MyCustomEventArgs> MyCustomEvent;
// Not "necessary" anymore..
// public delegate void MyCustomEventHandler(MyCustomEventArg evt);
public class MyObject{ /* ... */}
public class MyCustomEventArg : EventArgs
{
private MyObject _value;
public MyObject Data
{
get { return _value; }
set { _value = value; }
}
public MyCustomEventArg(MyObject value)
{
_value = value;
}
}

Well, that saved me one line of code! I can ditch work early today :-)

Wouldn’t it by nice if I could cut out the whole MyCustomEventArg class? that would save some more lines of code,

and prevent my head from hitting the desk and busting my skull on an upside-down thumb tack.

Well, that’s pretty easy to do: create a new class using generics. It supports a single object as a parameter which

can be passed in at construction.

using System;
/// <summary>
/// Encapsulates a single object as a parameter for simple event argument passing
/// <remarks>Now you can declare a simple event args derived class in one wrap</remarks>
/// <code>public void delegate MyCustomeEventHandler(TypedEventArg&lt;MyObject&gt; theSingleObjectParameter)</code>
/// </summary>
public class TypedEventArg<T> : EventArgs
{
private T _Value;
public TypedEventArg(T value)
{
_Value = value;
}
public T Value { get; set;}
}

Now the code can look like

public event MyCustomEventHandler MyCustomEvent;
public delegate void MyCustomEventHandler(TypedEventArg<MyObject> evt);
public class MyObject { /* ... */ }
//This whole thing now goes away..
//public class MyCustomEventArg : EventArgs
//{
// private MyObject _value;
// public MyObject Data { get; set; }
//
// public MyCustomEventArg(MyObject value)
// {
// _value = value;
// }
//}

And life is good. I do have to declare the delegate though, so you daring enough to type 2 nested angled brackets, you can go for the gold:

public event EventHandler<TypedEventArg<MyObject>> MyCustomEvent;
// public delegate void MyCustomEventHandler(TypedEventArg<MyObject> evt);
public MyObject Data { get; set; }

This lets you dispense with 1 extra line of code so for those of us typing with 1 or 2 fingers, life is better. Readability of nested generic references vs. the declaration of a delegate is a matter of taste mostly.

Taste would also guide you as to whether you like the declaration on the event consumer side better:

In case of a full delegate declaration:

Eventful eventSource = new Eventful();
eventSource.MyCustomEvent += new Eventful.SomethingHappenedEventHandler(OnSomethingHappenedEvent);

But if a generics EventHandler is used:

eventSource.MyCustomEvent += new EventHandler<TypedEventArg<MyObject>>(classWithEvent2_SomethingHappendedEvent);

In conclusion, by creating a simple generic type around EventArgs, I can save a few keystrokes and learn something while at it. Left as a future excercise : look at adding a constraint to the argument type such that the argument type is serializeable.

C# Generics - Interface declaration

I was challenged recently with a question about generics with constraints.

The claim was that it’s only a compile flaw that allows your to declare an interface for a generic type with a constraint. Namely that the syntax

public interface ISomething <T> where T: SomeClass

would pass compilation but would not be useful (runtime) because you can’t declare a variable

ISomething myVar = new ISomething<SomeClass>();

or something to that extent. I went home feeling a bit uneasy about the discussion, then coded this up the way I see it. While it is completely true that you can’t ‘new’ an interface, _using _an interface that has a generic type is completely possible and legal.

Here it is in all it’s g(l)ory.

using System;
using System.IO;
using System.Text;
/// Demo of generic interface declaration with constraint.
/// Showing compilation and runtime feasibility.
namespace NH.Demo
{
class Demo
{
static void Main(string[] args)
{
ITryInstance o1 = new GenericInstanceA();
ITry<MyDerivedType> o2 = new GenericInstanceB();
Console.WriteLine("Generic instance 1 " + o1.ProperT.SomeField);
Console.WriteLine("Generic instance 2 " + o2.ProperT.SomeField);
}
}
interface ITry<T> where T : MyBaseType
{
T ProperT{ get; }
}
public class MyBaseType
{
public string SomeField;
}
public class MyDerivedType : MyBaseType
{
public MyDerivedType(string arg)
{
base.SomeField = arg;
}
}
interface ITryInstance : ITry<MyDerivedType>
{
}
/// <summary>
/// this will fail. cosntraint violation
/// "The type 'string' must be convertible
/// to 'NH.Demo.MyBaseType' in order to use it as
/// parameter 'T' in the generic type or
/// method 'NH.Demo.ITry<T>'"
/// </summary>
//interface IFail : ITry<string> { }
public class GenericInstanceA : ITryInstance
{
MyDerivedType ITry<MyDerivedType>.ProperT
{
get { return new MyDerivedType("hi there!"); }
}
}
public class GenericInstanceB : ITry<MyDerivedType>
{
MyDerivedType ITry<MyDerivedType>.ProperT
{
get { return new MyDerivedType("hi there! again"); }
}
}
}

Workflow Custom Activity - Designer re-hosting

In developing some workflow stuff, ran across the need to create custom activities that “aggregate” other atomic activities into a larger activity. The idea is that

  1. Programmer codes some atomic activities, exposes appropriate Dependency Properties

  2. Non programmer

    1. Uses these atomics and creates processes using the atomic compiled activities
    2. Saves these composite activities as a new custom activity3. Can expose specific parameters for inner activities, but otherwise the activity is “locked” for the end user.
  3. End user

    1. Uses the composite activities to define a workflow and run it.
    2. Can bind runtime parameters to the composite activities.
  4. Runtime picks up an end user’s activity and runs it.

Gotcha’s:

  1. Designer re-hosting is a bit more complex than I would like it to be..

  2. Had to fool around with designer emitted dependency properties “Promote Bindable Properties” and ensure it would do the trick. This is the best way I found so far to expose inner properties of the atomic activities to the “surface” of the composite activities and allow the end user to assign values to them.

  3. Had to add to the compilation a ToolboxItem attribute (the re-hosting examples don’t do that, and since the non programmer does NOT have access to the code beside file, you have to add it within the designer compilation of the designer activity. The exact magic incantations are:

// add these lines to the workflow loader:
CodeAttributeDeclaration attrdecl = new CodeAttributeDeclaration(
"System.ComponentModel.ToolboxItem",
new CodeAttributeArgument(new CodePrimitiveExpression(true))
);
ctd.CustomAttributes.Add(attrdecl);
CodeCommentStatement nurisComment = new CodeCommentStatement(
new CodeComment("ToolboxItem decoration should do the trick.."));
ctd.Comments.Add(nurisComment);
// end added lines

Workflow custom Loop Activity

I was doing some workflow work and wanted to create a custom loop activity. The project needs it, and it’s a great way to learn what (not) to do.

The activity is a container that would loop through a list of discrete items (think foreach(string currentValue in ValueList)) and exposes the current loop variable via a bindable DependencyProperty.

The basics of the activity are to keep the container in “Executing” mode until all child activities are done. The tricky part is that the whole ActivityExecutionContext and ExecutionContextManager need to create for a new context each loop iteration. The hookup of the synchronization is done by using Activity.RegisterForStatusChange(.., OnEvent) on each child executed, then in the OnEvent() unregister the activity from further notice. I don’t love it, but it works.

Here goes:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Design;
namespace NH.Workflow
{
[Designer(typeof(SequenceDesigner),
typeof(IDesigner)),
ToolboxItem(typeof(ActivityToolboxItem)),
Description("Loop Activity - iterate over discrete list of items."),
ActivityValidator(typeof(LoopActivityValidator))]
public sealed class LoopActivity : CompositeActivity, IActivityEventListener<ActivityExecutionStatusChangedEventArgs>
{
private int currentIndex = 0;
private string[] valueList = { };
protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext)
{
if (base.EnabledActivities.Count == 0)
return ActivityExecutionStatus.Closed;
Activity firstChildActivity = base.EnabledActivities[0];
ActivityExecutionContext firstChildContext = executionContext.ExecutionContextManager.GetExecutionContext(firstChildActivity);
if (firstChildContext == null)
return ActivityExecutionStatus.Closed;
if (firstChildContext.Activity.ExecutionStatus == ActivityExecutionStatus.Executing)
firstChildContext.CancelActivity(firstChildContext.Activity);
return ActivityExecutionStatus.Canceling;
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
if (this.PerformNextIteration(executionContext))
return ActivityExecutionStatus.Executing;
else
return ActivityExecutionStatus.Closed;
}
void IActivityEventListener<ActivityExecutionStatusChangedEventArgs>.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs statusChangeEvent)
{
ActivityExecutionContext originContext = sender as ActivityExecutionContext;
statusChangeEvent.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this);
ActivityExecutionContextManager ctxManager = originContext.ExecutionContextManager;
ctxManager.CompleteExecutionContext(ctxManager.GetExecutionContext(statusChangeEvent.Activity));
if (!this.PerformNextIteration(originContext))
originContext.CloseActivity();
}
private bool PerformNextIteration(ActivityExecutionContext context)
{
if (((base.ExecutionStatus == ActivityExecutionStatus.Canceling)
|| (base.ExecutionStatus == ActivityExecutionStatus.Faulting))
|| currentIndex == valueList.Length)
{
return false;
}
this.CurrentValue = valueList[currentIndex++];
if (base.EnabledActivities.Count > 0)
{
ActivityExecutionContext firstChildContext = context.ExecutionContextManager.CreateExecutionContext(base.EnabledActivities[0]);
firstChildContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, this);
firstChildContext.ExecuteActivity(firstChildContext.Activity);
}
return true;
}
public static DependencyProperty ValueListProperty = System.Workflow.ComponentModel.DependencyProperty.Register("ValueList", typeof(string[]), typeof(LoopActivity));
/// <summary>
/// The list of values to iterate over. Child activities would be executed for each value in this list, and would be able to access the current value via the CurrentValue property.
/// </summary>
[Description("The values to iterate over")]
[Category("Other")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string[] ValueList
{
internal get
{
return valueList;
}
set
{
valueList = value;
}
}
public static DependencyProperty CurrentValueProperty = System.Workflow.ComponentModel.DependencyProperty.Register("CurrentValue", typeof(string), typeof(LoopActivity));
/// <summary>
/// The current value of the loop variable. This value changes each iteration and is used by child activities interested in the iteration value.
/// </summary>
[Description("The current loop value. Child activities should bind to this value if they are using the loop variable.")]
[Category("Other")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string CurrentValue
{
get
{
return ((string)(base.GetValue(LoopActivity.CurrentValueProperty)));
}
private set
{
base.SetValue(LoopActivity.CurrentValueProperty, value);
}
}
}
/// <summary>
/// Validator for the loop activity.
/// Check that the list of discrete items to iterate over is valid.
/// </summary>
public class LoopActivityValidator : ActivityValidator
{
public override ValidationErrorCollection ValidateProperties(ValidationManager manager, object obj)
{
ValidationErrorCollection errors = new ValidationErrorCollection();
LoopActivity activityToValidate = obj as LoopActivity;
if (activityToValidate.Parent != null) // prevent compile time checking.
{
if (activityToValidate == null)
errors.Add(new ValidationError("object passed in is not a LoopActivity", 1));
if (activityToValidate.ValueList == null)
errors.Add(new ValidationError("Value List not provided (it is null). Please provide a list of values to iterate over.", 2));
if (activityToValidate.ValueList.Length == 0)
errors.Add(new ValidationError("Value List not provided (it is empty). Please provide a list of values to iterate over.", 3));
}
return errors;
}
}
}

FasterTemplate c# code

So I wrote the thing up . Compared with a fairly common alternative, a run of the more type safe and render friendly template took 260 ms to merge 10k iterations vs. 480 ms for the alternative. In addition, the alternative went through almost twice the allocations (meaning more GC would result).
I’m kind of pleased that this is faster than the alternative, but am going to do some more thinking of a better way. A 46% reduction is nice, but it’s just under twice as fast. Still, the benefits of a cached template and token/key checking beats the alternative.
Toying with the idea of a strongly typed template leads to a dead end pretty much. Sure, one could dynamically emit a class that exposes the token names as properties, but then how would you bind to these in compile time? since the tokens are NOT known at compile time, the programmer using the class would have to populate a name value pair in some fashion, so that at run time the binding could be made.

//------------------------------------
namespace Nuri.FasterTemplate
{
public interface IFasterTemplate
{
string ID { get; }
void Render(System.IO.TextWriter writer, IRuntimeValues runtimeValues);
IRuntimeValues GetRuntimeValuesPrototype();
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
public interface IRuntimeValues
{
bool AddValue(string tokenName, string value);
bool AddValues(IEnumerable values);
string[] GetAllowedValues();
IRuntimeValues GetCopy();
bool IsAlowed(string tokenName);
string this[string tokenName] { get; }
string ID { get; }
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
public static class FasterTempateFactory
{
public static IFasterTemplate GetFasterTemplate(TokenConfiguration config, ref string template)
{
string id = Guid.NewGuid().ToString();
TemplateParts templateParts = processTemplateParts(id, config, ref template);
IRuntimeValues runtimeValuesPrototype = processTokens(id, templateParts);
IFasterTemplate result = new FasterTemplate(id, templateParts, runtimeValuesPrototype);
return result;
}
private static IRuntimeValues processTokens(string id, TemplateParts templateParts)
{
RuntimeValues result = new RuntimeValues(id);
for (int i = 0; i < templateParts.Count; i++)
if (templateParts[i].IsToken)
result[templateParts[i].Value] = string.Empty;
return result;
}
private static TemplateParts processTemplateParts(string id, TokenConfiguration config, ref string template)
{
TemplateParts result = new TemplateParts();
char currentChar;
bool isToken = false;
StringBuilder sbText = new StringBuilder(template.Length / 2);
StringBuilder sbToken = new StringBuilder(64);
for (int idx = 0; idx < template.Length; idx++)
{
currentChar = template[idx];
if (currentChar == config.TokenStartMarker)
{ isToken = true; result.Add(new TemplatePart(sbText.ToString(), false)); sbText.Length = 0; }
else if (currentChar == config.TokenEndMarker) { isToken = false; result.Add(new TemplatePart(sbToken.ToString(), true)); sbToken.Length = 0; } else { if (isToken) sbToken.Append(currentChar); else sbText.Append(currentChar); }
} if (isToken == true) throw new ArgumentException("Template has unclosed token marker"); if (sbText.Length > 0) result.Add(new TemplatePart(sbText.ToString(), false)); return result;
}
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
internal class FasterTemplate : IFasterTemplate
{
private string _ID;
private TemplateParts _TemplateParts;
private IRuntimeValues _RuntimeValuesPrototype;
internal FasterTemplate(string ID, TemplateParts templateParts, IRuntimeValues runtimeValuesPrototype) { _ID = ID; _TemplateParts = templateParts; _RuntimeValuesPrototype = runtimeValuesPrototype; } public IRuntimeValues GetRuntimeValuesPrototype() { return _RuntimeValuesPrototype.GetCopy(); } public string ID { get { return _ID; } }
public void Render(System.IO.TextWriter writer, IRuntimeValues runtimeValues)
{
if (runtimeValues.ID != this._ID) throw new ArgumentException("The runtime values supplied are not compatible with this template! Ensure you got the runtime values object from the template with ID " + this._ID); for (int i = 0, count = _TemplateParts.Count; i < count; i++)
{
TemplatePart part = _TemplateParts[i]; if (part.IsToken) { writer.Write(runtimeValues[part.Value]); }
else
{
writer.Write(part.Value);
}
}
}
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
internal class RuntimeValues : Nuri.FasterTemplate.IRuntimeValues
{
private Dictionary<string,string> _AllowedValues;
internal string _ID;
internal RuntimeValues(string ID, int capacity)
{
_AllowedValues = new Dictionary<string, string>(capacity);
_ID = ID;
}
internal RuntimeValues(string ID) : this(ID, 0x10) { }
internal Dictionary<string,string> AllowedValues
{
get { return _AllowedValues; }
}
public string[] GetAllowedValues()
{
string[] result = new string[_AllowedValues.Count];
int i = 0;
foreach (string key in _AllowedValues.Keys)
{ result[i++] = key; }
return result;
}
public bool IsAlowed(string tokenName)
{
return _AllowedValues.ContainsKey(tokenName);
}
public bool AddValue(string tokenName, string value)
{
if (_AllowedValues.ContainsKey(tokenName))
{
_AllowedValues[tokenName] = value;
return true;
}
else
return false;
}
public bool AddValues(IEnumerable values)
{
bool result = true;
foreach (KeyValuePair<string, string> pair in values)
{
result = result && this.AddValue(pair.Key, pair.Value);
}
return result;
}
public string this[string tokenName]
{
get
{
return _AllowedValues[tokenName];
}
internal set
{ _AllowedValues[tokenName] = value; }
}
public IRuntimeValues GetCopy()
{
RuntimeValues result = new RuntimeValues(this._ID, _AllowedValues.Count);
foreach (string key in _AllowedValues.Keys)
result.AllowedValues[key] = string.Empty;
return result;
}
public string ID
{
get { return _ID; }
}
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
internal struct TemplatePart
{
public bool IsToken;
public string Value;
public TemplatePart(string value, bool isToken)
{
this.Value = value;
this.IsToken = isToken;
}
}
}
//------------------------------------
namespace Nuri.FasterTemplate
{
class TemplateParts : List<TemplatePart> { }
}
//------------------------------------
namespace Nuri.FasterTemplate
{
public struct TokenConfiguration
{
public readonly char TokenStartMarker;
public readonly char TokenEndMarker;
public TokenConfiguration(char tokenStartMarker, char tokenEndMarker)
{
TokenStartMarker = tokenStartMarker;
TokenEndMarker = tokenEndMarker;
}
}
}

Runtime token substitution

I’m toying with a class that will allow for efficient token replacement at runtime.

Why re-invent the wheel?

  1. Its fun.

  2. A bare class that does just this is rare.

  3. Absent a class like this, people just use all kinds of string manipulation techniques that can be slow and sluggish.

What am I out to solve?

Let’s say your website supports some notion of a CMS. So you let some users publish pages / content by filling in a form and storing the content in the db. Next usually comes the request that special variables can be planted in the content. This includes ads, formatting, dynamic links, personalization data etc. The first reflex is to just use string replacement. But if the content is not the whole page, the tendency is to assign the string to a literal or somehow just create a string field in your page and then assign it to some code in front control. The issue with this is that at the very best, the input string (template) is scanned every time in order to determine where the token markers are. At the very worst this is combined with string thrashing and ends up being a wasteful string concatenation exercise. Me thinks a factory class TemplateFactory can generate an immutable template class. That class can be cached for a long time. The template innards would all be private and hidden. They would consist of all the static parts and all the “holes”. The template will be in itself a factory, letting a user get an instance of a RuntimeValue object. The runtime value object will support a .Add(TokenName, TokenValue) method, which would check the token names and be bound to the originating factory (the template that created it). This way, you get some runtime checking of invalid token assignments. The template would expose a method Render(writer, runtimeValues) . The render method would be the one merging the template with the runtime values. Notably, there would NOT be a string MergeValues(values) call. That’s because strings are immutable and storing the merged string at any scope is a waste. The only reason one would need to store it is for later use in a stream context (IIS response stream, mail message, file etc).

If this pains anyone, the use of StringWriter is recommended. But the intended use of this scheme is to plant the Render() call somewhere in the OnRender() event equivalent of your application. The idea is that the object would both enforce a correct (IMHO) deferral of merging to the presentation time, and implement an efficient algorithm for fast merges. The instance creation is going to bear the grunt of parsing the template and scanning for token markers. If a CMS system is the target app, it can pre create these runtime objects and keep them in memory. A template object would specifically NOT be created each time you need to merge. Only the lightweight RuntimeValues need to be gotten from a factory and populated each time, because these are the real runtime instance variants. The rest of the template is “static”.