Summary: This article is intended to give you a general idea about what’s functoid in BizTalk. Functoid is no more than a piece of .Net code whichn can perform a complete function.
1. Get Reflector ready before we get started. It can help us to disassemble DLLs and executables, get it from http://www.aisto.com/roeder/dotnet
2. Prepare functoids assembly, once you have BizTalk installed, Microsoft.BizTalk.BaseFunctoids.dll can be found on your machine.
3. Open Microsoft.BizTalk.BaseFunctoids.dll in Reflector and expand this DLL you can find many classes/enumerations such as AssertFunctoid, BaseFunctoid, etc. Take a look at the following screenshot for reference.

4. Every functoid is a class. Just right click on one class you want and select Disassemble. Sorry, I choose BaseFunctoidIDs here, it is an enumeration type. Basically it contains all the functoids coming with BizTalk 2006 R2. (I use BizTalk 2006 R2, I cannot guarantee you can get the same result if you are working with other versions).

BaseFunctoidIDs
1
[ComVisible(true)]
2
public enum BaseFunctoidIDs
3

{
4
Assert = 0x2c3,
5
ConvertAsc = 0x7e,
6
ConvertChr = 0x7f,
7
ConvertHex = 0x80,
8
ConvertOct = 0x81,
9
Count = 0x142,
10
CumulativeAvg = 0x145,
11
CumulativeConcat = 0x148,
12
CumulativeMax = 0x147,
13
CumulativeMin = 0x146,
14
CumulativeSum = 0x144,
15
DateAddDays = 0x7a,
16
DateCurrentDate = 0x7b,
17
DateCurrentDateTime = 0x7d,
18
DateCurrentTime = 0x7c,
19
DBErrorExtract = 0x23f,
20
DBLookup = 0x20c,
21
DBValueExtract = 0x23e,
22
ExistenceLooping = 0x321,
23
Index = 0x143,
24
IsNil = 0x2c2,
25
Iteration = 0x1da,
26
KeyMatch = 800,
27
LogicalAnd = 0x141,
28
LogicalEq = 0x13b,
29
LogicalExistence = 0x2bd,
30
LogicalGt = 0x137,
31
LogicalGte = 0x138,
32
LogicalIsDate = 0x13e,
33
LogicalIsNumeric = 0x13f,
34
LogicalIsString = 0x13d,
35
LogicalLt = 0x139,
36
LogicalLte = 0x13a,
37
LogicalNe = 0x13c,
38
LogicalNot = 0x2c1,
39
LogicalOr = 320,
40
Looping = 0x1a8,
41
MassCopy = 0x322,
42
MathAbs = 0x6f,
43
MathAdd = 0x76,
44
MathDivide = 0x79,
45
MathInt = 0x70,
46
MathMax = 0x71,
47
MathMin = 0x72,
48
MathMod = 0x73,
49
MathMultiply = 120,
50
MathRound = 0x74,
51
MathSqrt = 0x75,
52
MathSubtract = 0x77,
53
NilValue = 0x178,
54
SciArcTan = 130,
55
SciCos = 0x83,
56
SciExp = 0x86,
57
SciExp10 = 0x88,
58
SciLog = 0x87,
59
SciLog10 = 0x89,
60
SciLogn = 0x8b,
61
SciPow = 0x8a,
62
SciSin = 0x84,
63
SciTan = 0x85,
64
Scripter = 260,
65
StringConcatenate = 0x6b,
66
StringFind = 0x65,
67
StringLeft = 0x66,
68
StringLowerCase = 0x67,
69
StringRight = 0x68,
70
StringSize = 0x69,
71
StringSubstring = 0x6a,
72
StringTrimLeft = 0x6c,
73
StringTrimRight = 0x6d,
74
StringUpperCase = 110,
75
TableExtractor = 0x2c0,
76
TableLooping = 0x2bf,
77
ValueMapping = 0x177,
78
ValueMappingFlattening = 0x176,
79
XPath = 0x2be
80
}
81
82
83
5. Now I am choosing BaseFunctoid. It is a little big; every specific functoid will inherit from this abstract class.

BaseFunctoid
1
public abstract class BaseFunctoid
2

{
3
// Fields
4
private Bitmap myBitmap;
5
private Bitmap myBitmap16;
6
private FunctoidCategory myCategory;
7
private string myDescription;
8
private string myExternalAssembly;
9
private string myExternalAssemblyPartialName;
10
private string myExternalAssemblyPath;
11
private string myExternalClassName;
12
private string[] myExternalFunctionNames = new string[3];
13
private bool myHasSideEffects = true;
14
private bool myHasVariableInputs = false;
15
private int myID;
16
private InlineGlobalHelperFunction myInlineGlobalHelperFunctions = InlineGlobalHelperFunction.None;
17
private IList myInputConnectionTypeList = new ArrayList();
18
private Hashtable myMapScriptInfoCache = new Hashtable();
19
private int myMaxParams = -1;
20
private int myMinParams = -1;
21
private string myName;
22
private ConnectionType myOutputConnectionType;
23
private IDictionary myResMgrDict = new Hashtable();
24
private string myResourceAssemblyName;
25
private Hashtable myScriptBuffers = new Hashtable();
26
private Hashtable myScriptGlobalsBuffers = new Hashtable();
27
private Hashtable mySupportedScriptTypes = new Hashtable();
28
private string myTooltip;
29
30
// Methods
31
protected BaseFunctoid()
32
{
33
}
34
35
protected void AddInputConnectionType(ConnectionType connType)
36
{
37
this.myInputConnectionTypeList.Add(connType);
38
}
39
40
public void AddScriptTypeSupport(ScriptType scriptType)
41
{
42
if (!this.mySupportedScriptTypes.ContainsKey(scriptType))
43
{
44
this.mySupportedScriptTypes[scriptType] = true;
45
}
46
this.ClearScriptInfoCache(scriptType);
47
}
48
49
protected string BuildDynamicScriptHeader(string functionName, string returnType, string paramType, int numParams)
50
{
51
StringBuilder builder = new StringBuilder();
52
builder.Append("public ");
53
builder.Append(returnType);
54
builder.Append(" ");
55
builder.Append(functionName);
56
builder.Append("(");
57
for (int i = 0; i < numParams; i++)
58
{
59
if (i > 0)
60
{
61
builder.Append(", ");
62
}
63
builder.Append(paramType);
64
builder.Append(" param");
65
builder.Append(i.ToString(CultureInfo.InvariantCulture));
66
}
67
builder.Append(")\n");
68
return builder.ToString();
69
}
70
71
private void ClearScriptInfoCache(ScriptType scriptType)
72
{
73
if (this.myMapScriptInfoCache.ContainsKey(scriptType))
74
{
75
this.myMapScriptInfoCache.Remove(scriptType);
76
}
77
}
78
79
public static BaseFunctoid CreateScripterClone(BaseFunctoid functoidOrig)
80
{
81
if (functoidOrig == null)
82
{
83
throw new ArgumentNullException("functoidOrig");
84
}
85
BaseFunctoid functoid = new ScripterFunctoid();
86
functoid.myResourceAssemblyName = functoidOrig.myResourceAssemblyName;
87
functoid.myID = functoidOrig.myID;
88
functoid.myName = functoidOrig.myName;
89
functoid.myTooltip = functoidOrig.myTooltip;
90
functoid.myDescription = functoidOrig.myDescription;
91
functoid.myCategory = functoidOrig.myCategory;
92
functoid.myBitmap = functoidOrig.myBitmap;
93
functoid.myBitmap16 = functoidOrig.myBitmap16;
94
functoid.myCategory = functoidOrig.myCategory;
95
functoid.myMinParams = functoidOrig.myMinParams;
96
functoid.myMaxParams = functoidOrig.myMaxParams;
97
functoid.myOutputConnectionType = functoidOrig.myOutputConnectionType;
98
functoid.myInputConnectionTypeList = functoidOrig.myInputConnectionTypeList;
99
functoid.myHasVariableInputs = functoidOrig.myHasVariableInputs;
100
functoid.myResMgrDict = functoidOrig.myResMgrDict;
101
functoid.myInlineGlobalHelperFunctions = functoidOrig.myInlineGlobalHelperFunctions;
102
return functoid;
103
}
104
105
public ScriptType GetBestSupportedScriptType(ArrayList listScriptTypePrecedence)
106
{
107
if (listScriptTypePrecedence != null)
108
{
109
foreach (ScriptTypePrecedenceNode node in listScriptTypePrecedence)
110
{
111
if (((node != null) && node.Enabled) && this.mySupportedScriptTypes.ContainsKey(node.ScriptType))
112
{
113
return node.ScriptType;
114
}
115
}
116
}
117
return ScriptType.None;
118
}
119
120
protected string GetExternalFunctionName(int functionNumber)
121
{
122
if ((functionNumber < 0) || (functionNumber >= this.myExternalFunctionNames.Length))
123
{
124
throw new ArgumentOutOfRangeException("functionNumber", BaseFunctoidsResourceManager.GetResourceString("IDS_INVALID_FUNCTOID_FUNCTION_NUMBER"));
125
}
126
return this.myExternalFunctionNames[functionNumber];
127
}
128
129
public string GetFunctionName(ScriptType scriptType)
130
{
131
return this.GetFunctionName(scriptType, 0);
132
}
133
134
public string GetFunctionName(ScriptType scriptType, int functionNumber)
135
{
136
if (!IsValidScriptType(scriptType))
137
{
138
throw new ArgumentOutOfRangeException("scriptType", BaseFunctoidsResourceManager.GetResourceString("IDS_INVALID_SCRIPT_TYPE"));
139
}
140
if (!this.IsValidFunctionNumber(functionNumber))
141
{
142
throw new ArgumentOutOfRangeException("functionNumber", BaseFunctoidsResourceManager.GetResourceString("IDS_INVALID_FUNCTOID_FUNCTION_NUMBER"));
143
}
144
if (functionNumber == 0)
145
{
146
return this.UpdateScriptInfoCache(scriptType).MethodName;
147
}
148
switch (scriptType)
149
{
150
case ScriptType.ExternalAssembly:
151
return this.GetExternalFunctionName(functionNumber);
152
153
case ScriptType.Xslt:
154
return "";
155
}
156
return this.GetScriptingLanguageFunctionName(scriptType, functionNumber);
157
}
158
159
public static string GetInlineGlobalHelperScriptBuffer(ScriptType scriptType, InlineGlobalHelperFunction functions)
160
{
161
switch (scriptType)
162
{
163
case ScriptType.VbNet:
164
return GetInlineGlobalHelperScriptBufferVbNet(functions);
165
166
case ScriptType.CSharp:
167
return GetInlineGlobalHelperScriptBufferCSharp(functions);
168
169
case ScriptType.JScript: