LINQ to XML - creating an XML file from data collection

One of the final requirements for our MAMLConverter project is to output the processed html tags (which resides in a List<ElementEnt> collection) and generate a XML file from it. 

Our Data Layer (of type IHTMLData) has a SaveData() method which does the job nicely using LINQ to XML:

public bool SaveData(List<ElementEnt> dataList)

{

    // TODO: Use filename (xml extension) of file submitted to workflow

    string fileName = "temp.xml";

 

    var xml = new XElement("developerConceptualDocument",

            new XAttribute("snlmx", Resources.snlmx),

            new XAttribute("snlmx_xlink", Resources.snlmx_xlink),

        (from d in dataList

        where d.MAMLTag != null  && !d.IsIgnore  && !d.IsCloseTag

        select new XElement(d.MAMLTag, d.Content)));

 

    // Final cleanup.  LINQ XML complains if we attempt to use

    // xmlns as a tag so we'll resolve after it is done above.

    xml.ToString()

        .Replace("snlmx_xlink", "xmlns:xlink")

        .Replace("snlmx", "xmlns")

        .StrToFile(fileName);

 

    // TODO: Remove - FOR DEVELOPMENT PURPOSES

    Process.Start(fileName);

    return true;

}
The data structure it has to work with follows:

 

 

[TestMethod]

public void TestSaveProcessedListAsXML()

{

    BootStrapper bootStrap = new BootStrapper();

    string fileName = string.Format(mockFileName, CurrentDir);

 

    IHTMLData dll = bootStrap.UnityContainer.Resolve<IHTMLData>();

    if (dll.LoadData(fileName))

    {

        MAMLState state = bootStrap.UnityContainer.Resolve<MAMLState>();

        state.HtmlData = dll.GetHtmlData();

 

        using (MAMLWorkflowRuntime wfrt =

            new MAMLWorkflowRuntime(bootStrap.UnityContainer))

        {

            wfrt.Start(typeof(HtmlToMAML));

            Assert.IsTrue(dll.SaveData(wfrt.State.Data.HtmlData)); 

            Assert.AreEqual(22, wfrt.State.Data.HtmlData.Count); 

        }

    }

    else

        Assert.Fail(dll.Exception.Message);

 

    Assert.Fail("Keep Unit Test checked for development");

}

Note below that we only have a few tags currently defined (resource file and TagCommands) so we still have some work to do.  We'll also have to do some special post processing but for the most part have the core requirement's infrastructure in place.  I've been able to complete the input/output of data easily/efficiently because of LINQ to XML.

 BEFORE

AFTER
 


Tags: , , ,
Categories: LINQ | MAML | Workflow


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Workflow - separation of concerns

I'm enjoying workflow emmensely, I particularly like that we're forced to code in a manner that has us focus on the concerns of the Activity's Use Case.

For example the TagProcessorActivity and ElementProcessorActivity represented below:

Each of the above activities (pointed to by arrows) have a CodeActivity, SetCurrentElementCode and HtmlTagCode respectively; these code activities have a sole purpose in life.   The HtmlTag's purpose is to update/set the MAMLTag property to the value returned by the ProcessorService (service is set in SequenceActivityBase via Unity container).

The TagProcessorActivity (executes first) has the sole responsibility of setting the current element; the ReplicatorActivity provides us a CurrentIndex to notify us of our position in the Replicator list.  The TagProcessorActivity uses a method on our DataState object (of type IMAMLState) to update our state object; an excerpt from the MAMLState class follows:

/// <summary>

/// Sets the current element.

/// </summary>

/// <param name="activity">The activity.</param>

/// <returns></returns>

public ElementEnt SetCurrentElement(Activity activity)

{

    if (activity == null || activity.Parent ==null)

        return null;

    if (!(activity.Parent.Parent != null

            && activity.Parent.Parent is ReplicatorActivity))

        return null;

 

    ReplicatorActivity grandParent =

        activity.Parent.Parent as ReplicatorActivity;

    ElementBeingProcessed = grandParent.CurrentIndex;

    CurrentElement = (ElementEnt)

        grandParent.InitialChildData[grandParent.CurrentIndex];

    return CurrentElement;

}

Note: the [Sequence]ActivityBase is responsible for setting up the Activity so that the state is available; an excerpt from the ActivityBase follows:

protected override void OnActivityExecutionContextLoad(IServiceProvider provider)

{

    IWFState<IMAMLState> State;

    base.OnActivityExecutionContextLoad(provider);

    State = provider

        .GetService(typeof(IWFState<IMAMLState>)) as IWFState<IMAMLState>;

    Logger = State.UnityContainer.Resolve<ILoggerFacade>();

    ProcessorService = State.UnityContainer.Resolve<ITagProcessorService>();

    DataState = State.Data;

 

    WireupActivity(this);

}

 

At each level of processing there is a clear, testable separation of concern.

 

Source code available at http://www.Codeplex.com/MAMLConverter


 


Tags: ,
Categories: MAML | Unity | Workflow


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Workflow - Replicator activity event processing different

The ReplicatorActivity does not respect the base class wireup events as it's Activity and SequenceActivity counterparts do.  This BLOG demonstrates how we can hook into the current activity's Status Change event. 

Note in the following Log activity that the LogMAMLConverterStarted events are firing where the  LogTagProcessorStarted events are not - these activities are both LoggerActivity and share the same baseclass.

Debug(None): !! ACTIVITY WIREUP LogMAMLConverterStarted
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(None): ==> LogMAMLConverterStarted STATUS CHANGE - Status: Executing  Result: None
Debug(None): ==> LogMAMLConverterStarted EXECUTING:
Debug(None): MAML Converter Workflow Started
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): No HTML Tag
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [html]
Debug(None): MAML Tag set by service [htmlMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [head]
Debug(None): MAML Tag set by service [headMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [Untitled 1]
Debug(None): Processing HTML Tag [title]
Debug(None): MAML Tag set by service [titleMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [title]
Debug(None): MAML Tag set by service [titleMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [head]
Debug(None): MAML Tag set by service [headMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [body]
Debug(None): MAML Tag set by service [bodyMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [Welcome to the MAMLConverter Guide. This reference will help you understand and use this utility]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [What is MAMLConverter]
Debug(None): Processing HTML Tag [h2]
Debug(None): MAML Tag set by service [h2MAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [h2]
Debug(None): MAML Tag set by service [h2MAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [The MAMLConverter is a utility that will allow you to create your help documents with your favorite editor (this utility was created using Expression Web content) and convert them to MAML]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [Example]
Debug(None): Processing HTML Tag [h2]
Debug(None): MAML Tag set by service [h2MAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [h2]
Debug(None): MAML Tag set by service [h2MAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [The following & HTML ]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [Will be converted to ]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [p]
Debug(None): MAML Tag set by service [pMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [body]
Debug(None): MAML Tag set by service [bodyMAML]
Debug(None): !! ACTIVITY WIREUP LogTagProcessorStarted
Debug(None): !! ACTIVITY WIREUP LogCurrentContent
Debug(None): !! ACTIVITY WIREUP LogNoHtmlTag
Debug(None): !! ACTIVITY WIREUP LogHasHtmlTag
Debug(None): !! ACTIVITY WIREUP LogMAMLTag
Debug(None): !! ACTIVITY WIREUP elementProcessorActivity1
Debug(None): !! ACTIVITY WIREUP tagProcessorActivity
Debug(High): Tag processor started
Debug(None): Content being processed [<Empty Line>]
Debug(None): Processing HTML Tag [html]
Debug(None): MAML Tag set by service [htmlMAML]
The thread '<No Name>' (0x1420) has exited with code 0 (0x0).

See http://www.CodePlex.com/MAMLConverter for source

 


Tags: , ,
Categories: MAML | Workflow


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

LINQ - Projection eases parsing HTML content into data collection

In regards to my http://www.CodePlex.com/MAMLConverter project I have completed the Workflow infrastructure (integrated Unity and logging).  The next requirement is to pass the Workflow a collection of HTML data so that it can translate HTML tags to MAML tags.   The entity I'm going to start with follows:

namespace Workflow.Library.Entities

{

    public class ElementEnt

    {

        public bool IsCloseTag { get; set; }

        public string Tag { get; set; }

        public int TagLen { get; set; }

        public int Len { get; set; }

        public string Content { get; set; }

        public string OriginalContent { get; set; }

    }

}

This Use Case requirement will have me convert the following HTML into a List<ElementEnt> collection:

With the help of my StringExtensions class (many of the extensions written specifically for this task) I'm able to get my results with the query that follows:

Now all that remains is to populate my List<ElementEnt> collection.   LINQ Projection makes this task easy with the few following code changes:

All that remains is to move this code into its own class and create the Unit Test.  I'll then be ready to create the Workflow activities that will handle each of the tags.

String Extensions source follows:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

using System.Web;

 

namespace Workflow.Library.Extensions

{

    public static class StringExtensions

    {

        /// <summary>

        /// HTMLs the decode.

        /// </summary>

        /// <param name="data">The data.</param>

        /// <returns></returns>

        public static string HtmlDecode(this string data)

        {

            return HttpUtility.HtmlDecode(data);

        }

        /// <summary>

        /// HTMLs the encode.

        /// </summary>

        /// <param name="data">The data.</param>

        /// <returns></returns>

        public static string HtmlEncode(this string data)

        {

            return HttpUtility.HtmlEncode(data);

        }

 

 

        /// <summary>

        /// Gets the length of the tag.

        /// </summary>

        /// <param name="da">The da.</param>

        /// <returns></returns>

        public static int GetTagLength(this string da)

        {

            int offsetSP = da.IndexOf(' ');

            int offset = da.IndexOf('>');

            if (offsetSP > 0 && offsetSP < offset)

                offset = offsetSP;

            if (offset < 1)

                offset = da.Length;

            //return offset;

            return offset;

        }

 

        /// <summary>

        /// Gets the tag.

        /// </summary>

        /// <param name="da">The da.</param>

        /// <returns></returns>

        public static string GetTag(this string da)

        {

            int offset = GetTagLength(da);

            string retValue = da.Substring(0, offset);

            if (retValue.StartsWith("/"))

                retValue = retValue.Substring(1);

            if (retValue.EndsWith(">"))

                retValue = retValue.Substring(0, retValue.Length - 1);

            return retValue;

        }

 

        /// <summary>

        /// Gets the content.

        /// </summary>

        /// <param name="da">The da.</param>

        /// <returns></returns>

        public static string GetContent(this string da)

        {

            int offset = da.GetTagLength() + 1;

            if (offset >= da.Length)

                return "";

            else

                return da.Substring(offset);

        }

 

 

        /// <summary>

        /// Send string to specified filename

        /// </summary>

        /// <param name="data"></param>

        /// <param name="fileName"></param>

        /// <returns></returns>

        public static bool StrToFile(this string data, string fileName)

        {

            //Check if the sepcified file exists

            if (System.IO.File.Exists(fileName) == true)

            {

                // If so then Erase the file first as in this case

                // we are overwriting

                System.IO.File.Delete(fileName);

            }

 

            //Create the file if it does not exist and open it

            FileStream oFs = new

                FileStream(fileName, FileMode.CreateNew, FileAccess.ReadWrite);

 

            //Create a writer for the file

            StreamWriter oWriter = new StreamWriter(oFs);

 

            //Write the contents

            oWriter.Write(data);

            oWriter.Flush();

            oWriter.Close();

 

            oFs.Close();

 

            return true;

        }

 

        /// <summary>

        /// Return file contents as string

        /// </summary>

        /// <param name="cFileName"></param>

        /// <returns></returns>

        public static string FileToStr(this string cFileName)

        {

            //Create a StreamReader and open the file

            StreamReader oReader = System.IO.File.OpenText(cFileName);

 

            //Read all the contents of the file in a string

            string lcString = oReader.ReadToEnd();

 

            //Close the StreamReader and return the string

            oReader.Close();

            return lcString;

        }

    }

}

 


Tags: , , ,
Categories: MAML


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know

Unity - a Workflow Trojan Horse

Workflow is very powerful but I felt crippled without the Unity Container that I've come to depend on heavily in any application, no matter how large or small.   Case in point a new utility I'm working on to convert HTML to MAML so that I can take advantage of Sandcastles Help File Builder's  ConceptualContent which consist of MAML formated help files (no HTML).  Workflow seems optimal for this purpose.  The first requirement is (was) to plug in a Unity Container.

Workflow does offer the ability to register services that can be accessed from within activities, all that is required is to set an ExternalDataExchange attribute on your interface:

[ExternalDataExchange]

public interface IWFState<T>

{

    T Data { get; set; }

    IUnityContainer UnityContainer { get; set; }

    ILoggerFacade Logger { get; set; }

    void WireupActivity(Activity activity);

}

Then you load the service

public IWFState<T> State

{

    get { return _state; }

    set

    {

        _state = value;

        OnStateSet();

    }

}
/// <summary>

/// Loads the local services.

/// </summary>

public virtual void LoadLocalServices()

{

    ExternalDataExchangeService localServices = 
         new ExternalDataExchangeService();

    AddService(localServices);

    localServices.AddService(State);

}

 

However, this requires a redundant registration process (since I've already registered services with Unity).   I decided to use Unity as a trojan horse; I'll load one service, my state object which contains my UnityContainer, and then use my existing services via a UnityContainer property.  Important note:  some activities, i.e., Replicator and While will have to serialize referenced objects; any interfaces that Unity has to resolve in these activities will have to have [Serializable] attributes;

This permits my Activity to look as follows (ActivityBase has a UnityContainer property that returns State.UnityContainer):

namespace MAMLConvert.Activities.Logger

{

    /// <summary>

    /// Debug Logger

    /// </summary>

    public partial class LoggerDebugActivity : ActivityBase

  {

    public LoggerDebugActivity()

    {

      InitializeComponent();

    }

        protected override ActivityExecutionStatus

            Execute(ActivityExecutionContext executionContext)

        {

            UnityContainer.Resolve<ILoggerFacade>().Log(

                "Logging via Unity in the Activity!",

                    Category.Debug, Priority.None);

 

            return base.Execute(executionContext);

        }

  }

}

/// <summary>

/// Tests the workflow base ensure args is set on empty constructor.

/// </summary>

[TestMethod]

public void TestMAMLWorkflowBaseStartsAssignedWorkflow()

{

    using (MAMLWorkflowRuntime wfrt = new MAMLWorkflowRuntime())

    {

        Assert.IsNotNull(wfrt.Container);

        Assert.IsTrue(wfrt.Args.Count > 0, 
               "Should contain at least a UnityContainer");

        Assert.AreEqual("Initialized", wfrt.State.Data.MockInfo);

        Assert.AreEqual(wfrt.State.Logger.GetType().FullName,

            MockContainer.Resolve<ILoggerFacade>().GetType().FullName);

 

        wfrt.Start(typeof(HtmlToMAML));

    }

}

 

The above unit test yields the following results: 

 

Debug(None): !! ACTIVITY WIREUP loggerDebug
Debug(None): !! ACTIVITY WIREUP loggerTrace
Debug(None): !! ACTIVITY WIREUP loggerMessageBox
Debug(None): !! ACTIVITY WIREUP loggerEmail
Debug(None): !! ACTIVITY WIREUP Logger
Debug(None): ==> Logger STATUS CHANGE - Status: Executing  Result: None
Debug(None): ==> Logger EXECUTING:
Debug(None): ==> loggerDebug STATUS CHANGE - Status: Executing  Result: None
Debug(None): ==> loggerDebug EXECUTING:
Debug(None): Logging via Unity in the Activity!
Debug(None): ==> loggerDebug STATUS CHANGE - Status: Closed  Result: Succeeded
Debug(None): ==> loggerDebug CLOSED:
Debug(None): ==> Logger STATUS CHANGE - Status: Closed  Result: Succeeded
Debug(None): ==> Logger CLOSED:

 

Source code available at http://www.CodePlex.com/MAMLConverter
 


Tags: , ,
Categories: MAML | Unity | Workflow


Actions: E-mail | Permalink |  Grammar/Typo/Better way? Please let me know