?? sqlitefunction.cs
字號:
Exception r = returnValue as Exception;
if (r != null)
{
_base.ReturnError(context, r.Message);
return;
}
}
switch (SQLiteConvert.TypeToAffinity(t))
{
case TypeAffinity.Null:
_base.ReturnNull(context);
return;
case TypeAffinity.Int64:
_base.ReturnInt64(context, Convert.ToInt64(returnValue, CultureInfo.CurrentCulture));
return;
case TypeAffinity.Double:
_base.ReturnDouble(context, Convert.ToDouble(returnValue, CultureInfo.CurrentCulture));
return;
case TypeAffinity.Text:
_base.ReturnText(context, returnValue.ToString());
return;
case TypeAffinity.Blob:
_base.ReturnBlob(context, (byte[])returnValue);
return;
}
}
/// <summary>
/// Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method.
/// </summary>
/// <param name="context">A raw context pointer</param>
/// <param name="nArgs">Number of arguments passed in</param>
/// <param name="argsptr">A pointer to the array of arguments</param>
internal void ScalarCallback(IntPtr context, int nArgs, IntPtr argsptr)
{
SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr)));
}
/// <summary>
/// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
/// </summary>
/// <param name="len1">Length of the string pv1</param>
/// <param name="ptr1">Pointer to the first string to compare</param>
/// <param name="len2">Length of the string pv2</param>
/// <param name="ptr2">Pointer to the second string to compare</param>
/// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
/// than the second.</returns>
internal int CompareCallback(int len1, IntPtr ptr1, int len2, IntPtr ptr2)
{
return Compare(_base.ToString(ptr1, len1), _base.ToString(ptr2, len2));
}
/// <summary>
/// The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method.
/// </summary>
/// <remarks>
/// This function takes care of doing the lookups and getting the important information put together to call the Step() function.
/// That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so
/// binary searches can be done to find the data.
/// </remarks>
/// <param name="context">A raw context pointer</param>
/// <param name="nArgs">Number of arguments passed in</param>
/// <param name="argsptr">A pointer to the array of arguments</param>
internal void StepCallback(IntPtr context, int nArgs, IntPtr argsptr)
{
int n = _base.AggregateCount(context);
long nAux;
object obj = null;
nAux = (long)_base.AggregateContext(context);
if (n > 1) obj = _contextDataList[nAux];
Step(ConvertParams(nArgs, argsptr), n, ref obj);
_contextDataList[nAux] = obj;
}
/// <summary>
/// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
/// </summary>
/// <param name="context">A raw context pointer</param>
/// <param name="nArgs">Not used, always zero</param>
/// <param name="argsptr">Not used, always zero</param>
internal void FinalCallback(IntPtr context, int nArgs, IntPtr argsptr)
{
long n = (long)_base.AggregateContext(context);
object obj = null;
if (_contextDataList.ContainsKey(n))
{
obj = _contextDataList[n];
_contextDataList.Remove(n);
}
SetReturnValue(context, Final(obj));
IDisposable disp = obj as IDisposable;
if (disp != null) disp.Dispose();
}
/// <summary>
/// Placeholder for a user-defined disposal routine
/// </summary>
/// <param name="disposing">True if the object is being disposed explicitly</param>
protected virtual void Dispose(bool disposing)
{
}
/// <summary>
/// Disposes of any active contextData variables that were not automatically cleaned up. Sometimes this can happen if
/// someone closes the connection while a DataReader is open.
/// </summary>
public void Dispose()
{
Dispose(true);
IDisposable disp;
foreach (KeyValuePair<long, object> kv in _contextDataList)
{
disp = kv.Value as IDisposable;
if (disp != null)
disp.Dispose();
}
_contextDataList.Clear();
_InvokeFunc = null;
_StepFunc = null;
_FinalFunc = null;
_CompareFunc = null;
_base = null;
_contextDataList = null;
GC.SuppressFinalize(this);
}
#if !PLATFORM_COMPACTFRAMEWORK
/// <summary>
/// Using reflection, enumerate all assemblies in the current appdomain looking for classes that
/// have a SQLiteFunctionAttribute attribute, and registering them accordingly.
/// </summary>
static SQLiteFunction()
{
SQLiteFunctionAttribute at;
System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies();
int w = arAssemblies.Length;
for (int n = 0; n < w; n++)
{
Type[] arTypes;
try
{
arTypes = arAssemblies[n].GetTypes();
}
catch (Reflection.ReflectionTypeLoadException e)
{
arTypes = e.Types;
}
int v = arTypes.Length;
for (int x = 0; x < v; x++)
{
if (arTypes[x] == null) continue;
object[] arAtt = arTypes[x].GetCustomAttributes(typeof(SQLiteFunctionAttribute), false);
int u = arAtt.Length;
for (int y = 0; y < u; y++)
{
at = arAtt[y] as SQLiteFunctionAttribute;
if (at != null)
{
at._instanceType = arTypes[x];
_registeredFunctions.Add(at);
}
}
}
}
}
#else
/// <summary>
/// Manual method of registering a function. The type must still have the SQLiteFunctionAttributes in order to work
/// properly, but this is a workaround for the Compact Framework where enumerating assemblies is not currently supported.
/// </summary>
/// <param name="typ">The type of the function to register</param>
public static void RegisterFunction(Type typ)
{
object[] arAtt = typ.GetCustomAttributes(typeof(SQLiteFunctionAttribute), false);
int u = arAtt.Length;
SQLiteFunctionAttribute at;
for (int y = 0; y < u; y++)
{
at = arAtt[y] as SQLiteFunctionAttribute;
if (at != null)
{
at._instanceType = typ;
_registeredFunctions.Add(at);
}
}
}
#endif
/// <summary>
/// Called by SQLiteBase derived classes, this function binds all user-defined functions to a connection.
/// It is done this way so that all user-defined functions will access the database using the same encoding scheme
/// as the connection (UTF-8 or UTF-16).
/// </summary>
/// <remarks>
/// The wrapper functions that interop with SQLite will create a unique cooke value, which internally is a pointer to
/// all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks.
/// </remarks>
/// <param name="sqlbase">The base object on which the functions are to bind</param>
/// <returns>Returns an array of functions which the connection object should retain until the connection is closed.</returns>
internal static SQLiteFunction[] BindFunctions(SQLiteBase sqlbase)
{
SQLiteFunction f;
List<SQLiteFunction> lFunctions = new List<SQLiteFunction>();
foreach (SQLiteFunctionAttribute pr in _registeredFunctions)
{
f = (SQLiteFunction)Activator.CreateInstance(pr._instanceType);
f._base = sqlbase;
f._InvokeFunc = (pr.FuncType == FunctionType.Scalar) ? new SQLiteCallback(f.ScalarCallback) : null;
f._StepFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.StepCallback) : null;
f._FinalFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.FinalCallback) : null;
f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback) : null;
if (pr.FuncType != FunctionType.Collation)
f._interopCookie = sqlbase.CreateFunction(pr.Name, pr.Arguments, f._InvokeFunc, f._StepFunc, f._FinalFunc);
else
f._interopCookie = sqlbase.CreateCollation(pr.Name, f._CompareFunc);
lFunctions.Add(f);
}
SQLiteFunction[] arFunctions = new SQLiteFunction[lFunctions.Count];
lFunctions.CopyTo(arFunctions, 0);
return arFunctions;
}
/// <summary>
/// Issued after the base connection is closed, this function cleans up all user-defined functions and disposes of them.
/// </summary>
/// <remarks>
/// Cleaning up here is done mainly because of the interop wrapper. It allocated memory to hold a reference to all the
/// delegates, and now must free that memory.
/// Freeing is done after the connection is closed to ensure no callbacks get hit after we've freed the cookie.
/// </remarks>
/// <param name="sqlbase">The base SQLite connection object</param>
/// <param name="ar">An array of user-defined functions for this object</param>
internal static void UnbindFunctions(SQLiteBase sqlbase, SQLiteFunction[] ar)
{
if (ar == null) return;
int x = ar.Length;
for (int n = 0; n < x; n++)
{
sqlbase.FreeFunction(ar[n]._interopCookie);
ar[n].Dispose();
}
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -