using System;
using System.Reflection;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.ComponentModel;
using System.Collections;
using System.Text;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using BrainTechLLC.ThreadSafeObjects;
namespace BrainTechLLC
{
public static class MockObjectRepository
{
private static string _saveFilename;
public static bool MockRecordingEnabled { get; set; }
public static bool MockReplayEnabled { get; set; }
internal static ThreadSafeLookup<Type, MockObjectsForClass> MockObjectsByClass = new ThreadSafeLookup<Type, MockObjectsForClass>();
public static int MockCount
{
get
{
int count = 0;
List<MockObjectsForClass> list1 = MockObjectsByClass.AllItems;
for (int n = 0; n < list1.Count; n++)
{
MockObjectsForClass mockClass = list1[n];
List<MockObjectsForMethod> mockMethods = mockClass.LookupByMethodName.AllItems;
for (int a = 0; a < mockMethods.Count; a++)
{
MockObjectsForMethod mockMethod = mockMethods[a];
count += mockMethod.LookupByParameters.AllTerminatingItemsList.Count;
}
}
return count;
}
}
public static int AddMockObjectsFromFile(string pathAndFileName)
{
int count = 0;
if (File.Exists(pathAndFileName))
{
byte[] bytes = File.ReadAllBytes(pathAndFileName);
ThreadSafeLookup<Type, MockObjectsForClass> loaded = bytes.DeserializeFromCompressedBinary() as ThreadSafeLookup<Type, MockObjectsForClass>;
List<MockObjectsForClass> allMockClasses = loaded.AllItems;
for (int n = 0; n < allMockClasses.Count; n++)
{
MockObjectsForClass mockClass = allMockClasses[n];
List<MockObjectsForMethod> mockMethods = mockClass.LookupByMethodName.AllItems;
for (int a = 0; a < mockMethods.Count; a++)
{
MockObjectsForMethod mockMethod = mockMethods[a];
List<KeyValuePair<List<int>, StoredParametersAndReturnValue>> allStored = mockMethod.LookupByParameters.AllTerminatingItemsList;
foreach (KeyValuePair<List<int>, StoredParametersAndReturnValue> kvpStored in allStored)
{
StoredParametersAndReturnValue stored = kvpStored.Value;
stored.UnpackageMockFromStorage(true, true);
mockClass.ClassType.RecordMockObjectReturnValue(mockMethod.MethodName, stored.Parameters.ToArray(), stored.ReturnValue);
count++;
}
}
}
}
return count;
}
public static int SaveMockObjectsToFile(string pathAndFileName)
{
byte[] bytes = MockObjectsByClass.SerializeToCompressedBinary();
File.WriteAllBytes(pathAndFileName, bytes);
return MockCount;
}
public static void EnableMockRecording(this Type t, bool enabled)
{
if (enabled)
MockRecordingEnabled = true;
MockObjectsForClass mocks = RetrieveMockObjectsForClass(t);
mocks.MockRecordingEnabled = enabled;
}
public static MockObjectsForClass RetrieveMockObjectsForClass(this Type t)
{
MockObjectsForClass result = MockObjectsByClass[t];
if (result == null)
{
result = new MockObjectsForClass() { ClassType = t, MockRecordingEnabled = true };
MockObjectsByClass.AddOrSet(t, result);
}
return result;
}
public static StoredParametersAndReturnValue GetMockObject(this Type t, string methodName, params object[] parameters)
{
// Retrieve the structure that holds all recorded objects for class type t
MockObjectsForClass mockObjects = RetrieveMockObjectsForClass(t);
// Calculate a list of hash values that can be used to uniquely identify parameter values
List<int> paramHash = GetParametersHash(parameters);
// Retrieve the structure that holds all recorded objects for a specific method name
MockObjectsForMethod methodMocks = mockObjects.GetMockObjectsForMethod(methodName);
// Find a pre-recorded return value for this class type, method name, and parameter values
StoredParametersAndReturnValue found = methodMocks.LookupByParameters.FindItem(paramHash.ToArray());
// The return value may need to be unpacked from compressed binary storage
if (found != null && found.IsPacked)
found.UnpackageMockFromStorage(true, true);
return found;
}
public static StoredParametersAndReturnValue RecordMockObjectReturnValue(this Type t, string methodName, object[] parameters, object returnValue)
{
// Retrieve the structure that holds all recorded objects for class type t
MockObjectsForClass mockObjects = RetrieveMockObjectsForClass(t);
// Calculate a list of hash values that can be used to uniquely identify parameter values
List<int> paramHash = GetParametersHash(parameters);
int[] paramsHashArray = paramHash.ToArray();
// Retrieve the structure that holds all recorded objects for a specific method name
MockObjectsForMethod methodMocks = mockObjects.GetMockObjectsForMethod(methodName);
// Find any existing stored parameters/return value associated with this combo of
// type, method name, and parameters.
StoredParametersAndReturnValue found = methodMocks.LookupByParameters.FindItem(paramsHashArray);
if (found == null)
found = new StoredParametersAndReturnValue();
else
methodMocks.LookupByParameters.RemoveTerminatingItem(paramsHashArray);
// Set up values in StoredParametersAndReturnValue
found.ListOfParameterHash = paramHash;
found.Parameters = new List<object>(parameters);
found.ReturnValue = returnValue;
// Add this instance of StoredParametersAndReturnValue to the lookup data structure
methodMocks.LookupByParameters.AddTerminatingItem(found, paramsHashArray);
return found;
}
public static List<int> GetParametersHash(object[] parameters)
{
List<int> results = new List<int>();
for (int n = 0; n < parameters.Length; n++)
{
int hash = GetHashForParameter(parameters[n]);
results.Add(hash);
}
return results;
}
public static void EnableRecording(string saveFilename)
{
_saveFilename = saveFilename;
MockRecordingEnabled = true;
MockReplayEnabled = false;
}
public static void FinishRecording()
{
if (!string.IsNullOrEmpty(_saveFilename))
{
SaveMockObjectsToFile(_saveFilename);
}
}
public static void EnablePlayback(string mockDataFileName)
{
if (!string.IsNullOrEmpty(mockDataFileName))
AddMockObjectsFromFile(mockDataFileName);
MockRecordingEnabled = false;
MockReplayEnabled = true;
}
public static int GetHashForParameter(object o)
{
if (o == null)
return -99;
int hash = 0;
if (o.ForEachIfArray<object>(delegate(object item) { hash += GetHashForParameter(item); }))
return hash;
return o.GetHashCode();
}
public static bool ForEachIfArray<T>(this object o, TDelegateGeneral<T> del) where T : class
{
return o.ForEachIfArray(o.GetType(), del);
}
public static bool ForEachIfArray<T>(this object o, Type t, TDelegateGeneral<T> del) where T : class
{
if (t.IsArray)
{
Array a = o as Array;
foreach (object item in a)
{
del(item as T);
}
return true;
}
return false;
}
public static bool DoIfType<T>(this object o, Type t, TDelegateGeneral<T> del) where T : class
{
if (typeof(T).IsAssignableFrom(t))
{
del(o as T);
}
return false;
}
}
}