January 21, 2015

MVVM/MVC/MVP Explained

There is a nice explanation here

The represent several ways to manage and coordinate the GUI but the important thing is that the model is always segregated from the GUI. Usually the model is described as some database classes but the Model can contain threads and timers and event publishers so this overly simplistic view does not do it any justice. I prefer to view the model as an API on the business logic. A good way to create a model is using test classes from a test framework (such as NUnit or MS-Test). Using a GUI framework is a dangerous approach because it encourages the use of GUI objects within the model, even a simple message dialog within some model code can throw a spanner in the works so to speak.

The View represents the UI components such as CSS, jQuery, html, WinForms, WPF, Silverlight, XAML

January 13, 2015

Reactive Extensions

Here is a good introduction to the main interfaces: http://introtorx.com/Content/v1.0.10621.0/02_KeyTypes.html
IObserver<T> - Reader/Consumer/Observer
IObservable<T> - Writer/Publisher/Observable sequence. [I find this interface name confusing.]
ISubject<in TSource, out TResult> - Represents an object that is both an observable sequence as well as an observer. Used in (non-reactive) samples but not in real situations.
In comparison to IEnumerable<T> where items are pulled out, in an IObservable<T> items are pushed in
A simple sample: Consider an image processing system in a factory that scans parts for results. The outcome of the scan could be one of three states
public enum ImageProcessingSystemResult
{
    Failed, // failed image processing check
    Passed, // succeeded  image processing check
    Indeterminate
}
Here is the publisher of the image processing system results:
// Publishes a sequence of ImageProcessingSystemResult to the observer
public class ImageProcessingSystemPublisher : IObservable<ImageProcessingSystemResult>
{
    public IDisposable Subscribe(IObserver<ImageProcessingSystemResult> observer)
    {
        // These results in this case are just published one after another
        observer.OnNext(ImageProcessingSystemResult.Passed); 
        observer.OnNext(ImageProcessingSystemResult.Passed);
        observer.OnNext(ImageProcessingSystemResult.Failed);
        observer.OnNext(ImageProcessingSystemResult.Passed);
        observer.OnCompleted();
        return Disposable.Empty;
    }
}
Here is a generic results observer:
// Reads/Observes a sequence of T and decides what to do with it
// Basically, what you want to do when you receive some data
public class MyObserver<T> : IObserver<T>
{
    public void OnNext(T value)
    {
        string output = value != null ? value.ToString() : "null";
        Console.WriteLine("Received value: {0}", output);
    }
    public void OnError(Exception error)
    {
        Console.WriteLine("Sequence faulted with exception: {0}", error.ToString());
    }
    public void OnCompleted()
    {
        Console.WriteLine("Sequence terminated");
    }
}
Here is how it all goes together:
public void UnreactiveSimpleTest()
{
    var imageProcessingSystemPublisher = new ImageProcessingSystemPublisher();
    var observer = new MyObserver<ImageProcessingSystemResult>();
    // Here is how the observer subscribes to the publisher
    using (imageProcessingSystemPublisher.Subscribe(observer))
    { }
}
Here is the output:
Received value: Passed
Received value: Passed
Received value: Failed
Received value: Passed
Sequence terminated

Press any key to continue ...

Hot and Cold Observables (i.e. publishers)


Cold - Sequences that start producing notifications on request (when subscribed to), and each subscriber gets a copy of the same notification stream from the beginning.
Hot - Sequences that are active and produce notifications regardless of subscriptions (just like c# events).

A 'Cold' Observable can be converted to a 'Hot' Observable by using the Publish() extension method. With a hot Observable it is necessary to use "Connect()" to connect to the published sequence. This returns an IDisposable which must be disposed of when the Observable sequence is finished with.

January 7, 2015

Reading Xml Using XDocument

The ideas behind this blog are revealed here
Wanted to read some objects in using XDocument.

Found that the best was to use the explicit cast operators exposed by XDocument. These can be used to protect against attributes and elements that are missing

Also found that the XDocument.Parse() method was an excellent way to use raw XML strings to test the parsing
Consider this class:
internal class Base 
{
 public int Id { get; set; }
 public string Name { get; set; }
 public string Faction { get; set; }
}
Here is some small test XML to parse:
string rawTestXml = @"
<Bases>
  <Base ID=""1""><NAME>Freeport 2</NAME><FACTION>Zoners</FACTION></Base>
  <Base ><NAME>Pacifica</NAME></Base>
</Bases>";
Here is a method to test parsing this XML:
public void TestXDocumentParseUnprotected()
{
    FreelancerData freelancerData = new FreelancerData();

    var xmlDoc = XDocument.Parse(rawTestXml);
    var basesTableRaw = new Dictionary<int, Base>();

    foreach (var bas in xmlDoc.Descendants("Base"))
    {
        var b = new Base()
        {
            Id = Convert.ToInt32(bas.Attribute("ID").Value),
            Name = bas.Element("NAME").Value,
            Faction = bas.Element("FACTION").Value,
        };

        basesTableRaw.Add(b.Id, b);
    }

    Debug.Assert(basesTableRaw.Count == 2);

}
This will throw an exception when parsing the second "Base" element in the Xml string, as this second object is missing an "ID" attribute a NullReferenceException will be thrown by the line to extract it. If the XML data can be guaranteed then this is not a problem. A more robust way to read in the XML is to use the XElement/Xattribute explicit conversion operators:
public void TestXDocumentParseProtected()
{
  var xmlDoc = XDocument.Parse(rawTestXml);
  var basesTableRaw = new Dictionary<int, Base>();

  foreach (var bas in xmlDoc.Descendants("Base"))
  {
    var b = new Base()
    {
      Id = (int?)bas.Attribute("ID") ?? 0,  // 0 when the attribute "ID" is not present
      Name = (string)bas.Element("NAME") ?? "",  // "" when the element "NAME" is not present
      Faction = (string)bas.Element("FACTION"), // null when the element "FACTION" is not present
    };

    basesTableRaw.Add(b.Id, b);
  }

  Debug.Assert(basesTableRaw.Count == 2);
}
However this is allowing malformed objects to be allowed as input. The developer must detect these and decide what to do with them.

Note that the XDocument.Load() method can be used to load a document from a local file system file or from a Url. So this method
public void LoadBases(string rootPath)
{
  string xmlFileName = "Bases.xml";
  string basesPath = Path.Combine(rootPath, xmlFileName);
  var xmlDoc = XDocument.Load(basesPath);
  
  ...
}
can work with a local file:
LoadBases(@"X:\Backup\Documents\flasp\");
or a url:
LoadBases(@"http://www.somewebserver.com/flasp/");

December 21, 2014

Weak References with Compiled Transforms

There is a good description of this generic WeakReference<> class here.
Here is an example of using WeakReferences for caching XslCompiledTransform's:
private static Dictionary<string, WeakReference<XslCompiledTransform>> xsltLookupTable = 
  new Dictionary<string, WeakReference<XslCompiledTransform>>();

public XslCompiledTransform GetCompiledTransform(string xslFileName)
{
    XslCompiledTransform xct = null;
    bool found = xsltLookupTable.ContainsKey(xslFileName);
    if (found) // IF the transform is already cached
    {   // Try and get it
        WeakReference<XslCompiledTransform> xctWr = xsltLookupTable[xslFileName] 
           as WeakReference<XslCompiledTransform>;
        xctWr.TryGetTarget(out xct); // Try and get it from the WeakReference
        m_logger.WriteTrace("Found XslCompiledTransform entry for \'" + 
           xslFileName + "\' in the cache");
        // Note the entry maybe null (if the weak reference expired)
    }
        
    if (xct == null) // IF the compiled transform was not already cached
    {
        // Create it
        xct = new XslCompiledTransform();
        xct.Load(xslFileName, 
          new XsltSettings { EnableDocumentFunction = true }, 
          new XmlUrlResolver());
        // Insert it into a WeakReference
        WeakReference<XslCompiledTransform> wr = new 
          WeakReference<XslCompiledTransform>(xct);
        if (found)
        {
          m_logger.WriteTrace("Removing XslCompiledTransform entry for \'" + 
              xslFileName + "\' as it was null in the cache");
          xsltLookupTable.Remove(xslFileName);
        }
        xsltLookupTable.Add(xslFileName, wr); // Add the WeakReference to the cache
        m_logger.WriteTrace("Adding XslCompiledTransform entry for \'" + 
          xslFileName + "\'");
    }
    return xct;
}
It uses the new generic WeakReference<> class (available in .NET 4.5?). This class could be further refactored into a generic caching class if it was required.

December 12, 2014

Configuring log4net for specific classes or namespaces

Here is some sample xml that goes in the application config file.
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    ...
  </configSections>
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="WARN" />
        <foreColor value="Yellow" />
      </mapping>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%utcdate [%t] %-5p [] - %m%n"/>
      </layout>
    </appender>
    <appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender">
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%utcdate [%t] %-5p %c [] - %m%n"/>
      </layout>
    </appender>
    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
      <file value="FilePath.txt" />
      <appendToFile value="true" />
      <maximumFileSize value="1000KB" />
      <maxSizeRollBackups value="20" />
      <param name="RollingStyle" value="Size" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%utcdate [%t] %-5p %c [] - %m%n" />
      </layout>
    </appender>
    <root>
      <level value="INFO"/>
      <appender-ref ref="RollingFile"/>
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="OutputDebugStringAppender"/>
    </root>
    <!--Level values are DEBUG, INFO, WARN, ERROR -->
    <!--Entries for "top level" server module classes, to allow tracing of method calls -->
    <logger name="Some.Name.Space.ClassA.">
      <level value="INFO"/>
    </logger>
    ...
    <!--Entries for namespaces, to allow full tracing inside modules -->
    <logger name="Some.Particular.Namespace">
      <level value="INFO"/>
    </logger>
    ...
    <!--Entries for certain individual classes -->
    <logger name="Some.Deep.Level.NameSpace.SpecificClass.">
      <level value="DEBUG"/>
    </logger>
    ...
  </log4net>
...  
</configuration>

December 5, 2014

Simple Logger using Caller Info Attributes

Since .NET 4.5 There are 3 caller info attributes that are filled in at compile time by the compiler CallerMemberName, CallerFilePath, and CallerLineNumber These strings are inserted at compile time so they are much faster than using reflection.

Here is an example of how to use it to make the simplest logger (only 1 method + 1 property):
using System.Runtime.CompilerServices;

public enum LoggingLevelEnum
{
    Debug = 1,
    Info = 2,
    Warning = 3,
    Error = 4,
    Fatal = 5
}

public interface ISimpleLogger
{
    LoggingLevelEnum LoggingLevel { get; set; }

    void Log(
        Func<string> message,
        LoggingLevelEnum level = LoggingLevelEnum.Debug,
        [CallerMemberName] string member = "",
        [CallerFilePath] string file = "",
        [CallerLineNumber] int line = -1)
}

public class SimpleLogger : ISimpleLogger
{
    public LoggingLevelEnum LoggingLevel { get; set; } = 
        LoggingLevelEnum.Debug;

    public void Log(
        Func<string> message,
        LoggingLevelEnum level = LoggingLevelEnum.Debug,
        [CallerMemberName] string member = "",
        [CallerFilePath] string file = "",
        [CallerLineNumber] int line = -1)
    {
        if (level >= LoggingLevel)
        {
            Trace.WriteLine($"{level.ToString().ToUpper()} Member: {member}, File: {file}, Line: {line} - {message()}");
        }
    }
}
and invoking it:
ISimpleLogger logger = new SimpleLogger();
...
catch(Exception ex)
{
  // The attributed parameters are inserted by the compiler at compile time
  logger.Log(() => { return " Exception caught " + ex.ToString(); }, LogLevelEnum.Error); 
}

Note: Why log using a function returning a string? So that if you have a complex expression for creating the message, it only gets evaluated if the logging level is sufficient. If there is a lot of logging and the logging level is high, it saves a lot of unecessary string concatenation occurring.


November 18, 2014

When is a Hyphen not a Hyphen?

Take a look at these 2 command line strings:
CASE 1:
"%windir%\Microsoft.NET\Framework\v2.0.50727\caspol.exe" -machine -addgroup All_Code 
-site 192.168.45.111 FullTrust -name "XXX : 192.168.45.111" -description 
"Allows full trust privileges to XXX Public Safety Applications"
CASE 2:
"%windir%\Microsoft.NET\Framework\v2.0.50727\caspol.exe" -machine -addgroup All_Code 
-site 192.168.45.111 FullTrust –name "XXX : 192.168.45.111" –description 
"Allows full trust privileges to XXX Public Safety Applications"

While the first one succeds the 2nd one fails. When we converted the "-name" in the first one to hex we got
2D6E616D65
Whereas in the second we got
966E616D65

The hyphen in the first is a hyphen but in the second one it is in fact a "non-breaking hyphen". This is just visible in this email but in a notepad editor they may look exactly the same.
The morale of the story is: Beware of command line arguments copied from 3rd party sources