Forwarding events in C#
Yesterday I learned a new syntax in C# that I didn't know about. I learned how you can forward events. Let's say I want a class that takes a schema, and validates html to that schema. The class would encapsulate the XmlReaderSettings, but code from the outside would want to subscribe to the ValidationEventHandler on that private field. The code would look something like this.
public HtmlValidator(string @namespace, string schemaPath)
{
this.html = html;
/* Load the schema */
var xmlSchema = XmlReader.Create(schemaPath);
xmlValidationSettings = new XmlReaderSettings();
xmlValidationSettings.Schemas.Add(@namespace, xmlSchema);
xmlValidationSettings.ValidationType = ValidationType.Schema;
}
public void Validate(string html)
{
var htmlReader = new StringReader(html);
// Trigger this event on schema validation errors
// xmlValidationSettings.ValidationEventHandler += HandleValidationErrors;
// Read and validate htmlOutputStream
var xmlValidatingReader = XmlReader.Create(htmlReader, xmlValidationSettings);
while (xmlValidatingReader.Read()) ;
}
}
How could the code calling on Validate, subscribe to ValidationEventHandler on xmlValidationSettings? We would need to create an event on HtmlValidator that forwards the ValidationEventHandler. I add a public forwarding event like this.
Now we can subscribe to this event, and it will subscribe to the inner ValidationEventHandler. Study the following tests.
// Add event handler
var errors = 0;
validator.OnValidationError += (o, e) => errors++;
// Validate html
validator.Validate(html);
return errors;
}
[Test]
public void HtmlShouldBeValid()
{
var html = @"<ul xmlns=""urn:unordered-list""><li></li><li></li></ul>";
// Assert the result
Assert.That(this.CountHtmlErrors(html), Is.EqualTo(0));
}
[Test]
public void HtmlShouldBeInvalid()
{
var html = @"<ul xmlns=""urn:unordered-list""><p>Hello</p></ul>";
// Assert the result
Assert.That(this.CountHtmlErrors(html), Is.EqualTo(1));
}
}
At line 11 I subscribe to the external event that will trigger the error++ code on validation errors. Pretty neat, huh!?