The target (for this example) is to create an custom component that changes a date value to the next weekday (based on a stored function in a database). This component is used in a rule which should unter certain circumstances assign only weekdays to a date.
To achieve this on has first to imlement the actual class which mapps a date to the next weekday. In my case the next weekday is calculated in an stored function defined in our application database.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;
namespace Cubido.BizTalk.Tools
{
public class DateTool
{
public DateTool()
{
if(!EventLog.SourceExists("Cubido.BizTalk.Tools"))
EventLog.CreateEventSource("Cubido.BizTalk.Tools", "Cubido.BizTalk.Tools");
}
public string NextWeekDayString(DateTime date, string calendarId, string connectString)
{
try
{
SqlConnection con = new SqlConnection(connectString);
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = "SET DATEFIRST 1; SELECT dbo.JuxtaposedWorkdayAfter(@CalendarID, @Date)";
cmd.Parameters.Add("@CalendarID", SqlDbType.VarChar, 12).Value = calendarId;
cmd.Parameters.Add("@Date", SqlDbType.DateTime).Value = date;
date = (DateTime) cmd.ExecuteScalar();
con.Close();
}
catch(Exception e)
{
EventLog eventLog = new EventLog();
eventLog.Source = "Cubido.BizTalk.Tools";
eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
}
string curdate = date.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
string curtime = date.ToString("T",System.Globalization.CultureInfo.InvariantCulture);
return curdate + "T" + curtime + ".000";
}
}
}
A few thing are notable about this piece of code:
- the function NextWeekDayString returns a String and not a DateTime. Returning a DateTime resulted in some errors which I could not follow and with String as return value it works like a charm. The string representation of the date value is such that the date is recognized by the Microsoft SqlServer as valid date.
- The Parameter calendarId and connectString are just my way to specify the neccessary type of calendar used (the application allowes different calendars in different situations) and the connect string to our applications database. Both values are defined in the vocabulary as constants.
The second piece of code is not so ovious - but it is needed nevertheless. It's just a class needed by the rule composer for manageing the fact.
using System;
using Microsoft.RuleEngine;
namespace Cubido.BizTalk.Tools
{
///
/// Summary description for FactCreator.
///
public class FactCreator : IFactCreator
{
public object[] CreateFacts(RuleSetInfo rsi)
{
object[] o = new object[1];
o[0] = new Cubido.BizTalk.Tools.DateTool();
return o;
}
public Type[] GetFactTypes(RuleSetInfo rsi)
{
Type[] t = new Type[1];
t[0] = new Cubido.BizTalk.Tools.DateTool().GetType();
return t;
}
}
}
The interface FactCreator (implemented in an Assembly found in '...\Program Files\Microsoft BizTalk Server 2004\Microsoft.RuleEngine.dll') has to be imlemented and the content of the object array retured matches all the functions that should be accessed from the Business Rule Composer.
The assembly (or assemblies if you have more of them) have to reside in the global assembly cache. For me it was usefull to set the version of the assembly to '1.0.0.0' (in the AssemblyInfo.cs) and define a post build step which removes the old assembly and adds the new on from/to the GAC.
Having come so far the C# programming is over, the component can be used within the Business Rule Composer. To do so one must add the component in the Fact Explorer. After that it can be used within any rule either in the Condition part or in the Then part.
If you do some testing within the Business Rule Composer you have to add the Assembly with the class implementing the IFactCreator interface to the fact creators in the Test Policy dialog.
When the Rule is accessed from an orchestration, the class which implements the custom function has to be assigned to a variable (Variables -> New Variable) and provided as parameter in the Call Rule shape.