|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn this article, I present a class library which provides you a BackgroundSome of us have had a need for associative Using the CodeLet's say we have an public class Employee
{
SSN m_ssn; //SSN is IComparable
int m_id;
string m_firstName;
string m_lastName;
public Employee(int id, SSN ssn, string firstName, string lastName)
{
m_ssn = ssn;
m_id = id;
m_firstName = firstName;
m_lastName = lastName;
}
public SSN E_SSN
{
get { return m_ssn; }
set { m_ssn = value; }
}
public int E_ID
{
get { return m_id; }
set { m_id = value; }
}
public string LastName
{
get { return m_lastName; }
set { m_lastName = value; }
}
public string FirstName
{
get { return m_firstName; }
set { m_firstName = value; }
}
public override string ToString()
{
return "[" + m_id + "] " + m_firstName + " " +
m_lastName + " " + m_ssn.ToString();
}
}
Let's define a
As you would have noticed from the keys,
The above MIContainer<
Employee,
IndexedBy<
Employee,
UniqueKey<
Employee,
int,
IDTag
>,
UniqueKey<
Employee,
SSN,
SSNTag
>,
NonUniqueKey<
Employee,
string,
FirstNameTag
>,
NonUniqueKey<
Employee,
string,
LastNameTag
>
>
> container = new MIContainer<Employee, IndexedBy<Employee,
UniqueKey<Employee, int, IDTag>, UniqueKey<Employee,
SSN, SSNTag>, NonUniqueKey<Employee, string,
FirstNameTag>, NonUniqueKey<Employee, string, LastNameTag>>>
(new IndexedBy<Employee, UniqueKey<Employee, int, IDTag>,
UniqueKey<Employee, SSN, SSNTag>, NonUniqueKey<Employee,
string, FirstNameTag>, NonUniqueKey<Employee,
string, LastNameTag>>(
/*Unique Key on Employee ID*/
new UniqueKey<Employee, int, IDTag>("E_ID"),
/*Unique Key on Employee SSN*/
new UniqueKey<Employee, SSN, SSNTag>("E_SSN"),
/*Non Unique Key on First Name*/
new NonUniqueKey<Employee, string, FirstNameTag>("FirstName"),
/*Non Unique Key on Last Name*/
new NonUniqueKey<Employee, string, LastNameTag>("LastName")
)
);
The C'tor looks pretty nasty up there ;) and in future I would like to make it nicer than the current version. As you would notice, I have associated tags on all the Indices. Tags are defined as: public struct SSNTag : ITag { }
public struct IDTag : ITag { }
public struct FirstNameTag : ITag { }
public struct LastNameTag : ITag { }
public interface IMIContainer<ElemT>
{
void Add(ElemT elemt);
void Remove(Enumerators.IEnumerator<ElemT> iterator);
Index.IIndexedBy<ElemT> Indices { get; }
void Clear();
Enumerators.IEnumerator<ElemT> GetEnumerator();
void Foreach(Action<ElemT> action);
void Modify<KeyT>(IEnumerator<ElemT> keyEnumerator,
KeyModifier<ElemT> keyModifier);
}
Adding Elementscontainer.Add(
new Employee(
111, //Employee ID
new SSN("121", "22", "3232"), //SSN
"Parag", //First Name
"Gadkari" //Last Name
)
);
//Following will throw because Employee ID defined as UniqueKey index
container.Add(
new Employee(
111, //Employee ID
new SSN("922", "52", "0000"), //SSN
"Parag", //First Name
"Gadkari" //Last Name
)
);
//Following will throw because SSN is defined as UniqueKey index
container.Add(
new Employee(
151, //Employee ID
new SSN("121", "22", "3232"), //SSN
"Parag", //First Name
"Gadkari" //Last Name
)
);
//Following will *not* throw since FirstName and LastName are
//defined as NonUniqueKey indices.
container.Add(
new Employee(
1091, //Employee ID
new SSN("999", "52", "0000"), //SSN
"Parag", //First Name
"Gadkari" //Last Name
)
);
Accessing IndicesAll the indices derive from //Accessing using Tag Names
IIndex<Employee> index = container.Indices.Get<LastNameTag>();
//or
IIndex<Employee> index = container.Indices[typeof(LastNameTag)];
//or
IIndex<Employee> index = container.Indices.Get(typeof(LastNameTag));
//Accessing using Position
IIndex<Employee> index = container.Indices[3];
//or
IIndex<Employee> index = container.Indices.Get(3);
The following describes the public interface IIndex<ElemT>:Internals.IEnumerable<ElemT>
{
void Foreach(Action<ElemT> action);
void Sort();
Type Tag { get;}
}
For more functionalities (such as Sort/Find/Foreach Etc.IIndex<Employee> lastNameIndex = container.Indices.Get<LastNameTag>();
lastNameIndex.Sort();
lastNameIndex.Foreach(delegate(Employee empl)
{ Console.WriteLine(empl.ToString()); });
IIndex<string,Employee> exLastNameIndex = (IIndex<string,Employee>)lastNameIndex;
//Sort in a descending manner..
//this form of Sort function is only available in the IIndex<KeyT,ElemT> interface
exLastNameIndex.Sort(delegate(string key1, string key2)
{ return key2.CompareTo(key1); });
//Get SSN index
IIndex<SSN, Employee> indexSSN =
(IIndex<SSN, Employee>)container.Indices.Get<SSNTag>();
//Find SSN and Modify them
MultiIndexContainer.Enumerators.IEnumerator<Employee> enm =
indexSSN.Find(new SSN("121", "22", "3232"));
while (enm.MoveNext())
{
Console.WriteLine(enm.Current.ToString());
//Modify SSN
container.Modify<SSN>(enm, this.SSNModifier);
}
Modify/Update a KeyKey can be modified in using the following:
The difference between
//Using IIndex<KeyT,ElemT>
MultiIndexContainer.Enumerators.IEnumerator<Employee> emp =
fnameIndex.Find("Parag");
while (emp.MoveNext())
{
emp.Current.FirstName = "Pragaa";
}
//Using Modify method
fnameIndex.ModifyKey("Parag", "Pragaa");
//Or using Update method
fnameIndex.UpdateKey("Parag");
//OR
//Using IMIContainer
MultiIndexContainer.Enumerators.IEnumerator<Employee> enm =
indexSSN.Find(new SSN("121", "22", "3232"));
while (enm.MoveNext())
{
container.Modify<SSN>(enm, this.SSNModifier);
}
Erasing an ElementMultiIndexContainer.Enumerators.IEnumerator<Employee> emp =
fnameIndex.Find("Parag");
while (emp.MoveNext())
{
//Check condition and delete
container.Remove(emp);
}
Future WorkThis is what I can think of (listed in the order of priority):
Your comments on the work would really be appreciated and would allow me to make this library better. Thanks.:) History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||