Enhancing CAB's ManagedObjectCollection
For those who don't know, the ManagedObjectCollection registers its elements using the objects running type as part of the key.
Recently, I had the need to add and retrieve a component to the WorkItem's Items collection independently of its running. I only wanted to retrieve the component (using a ComponentDependency) with a specified name. Needless to say that I couldn't, because I was trying to retrieve an object, and that was not the running type of the object added to the WorkItem.
I started thinking of the ability of the ServiceCollection to add items registering them with a different type would be very helpfully to the ManagedObjectCollection. So, decided to add some changes.
To be able to build elements and register them with a different type, I had to change the Build method:
private TItem Build(Type typeToBuild, Type typeToRegisterAs, string idToBuild, object item)
{
if (idToBuild != null && Contains(idToBuild, SearchMode.Local, true))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
Properties.Resources.DuplicateID, idToBuild));
if (item != null && Object.ReferenceEquals(item,
locator.Get(new DependencyResolutionLocatorKey(typeof(WorkItem), null))))
throw new ArgumentException(Properties.Resources.CannotAddWorkItemToItself, "item");
if (item == null)
item = BuildFirstTimeItem(typeToBuild, typeToRegisterAs, idToBuild, null);
else if (!container.Contains(item))
item = BuildFirstTimeItem(typeToBuild, typeToRegisterAs, idToBuild, item);
else
BuildRepeatedItem(typeToBuild, typeToRegisterAs, idToBuild, item);
return (TItem)item;
}
private object BuildFirstTimeItem(Type typeToBuild, Type typeToRegisterAs, string idToBuild, object item)
{
item = builder.BuildUp(locator, typeToBuild, NormalizeID(idToBuild), item);
if (typeToRegisterAs != typeToBuild)
{
locator.Add(new DependencyResolutionLocatorKey(typeToRegisterAs, idToBuild), item);
locator.Remove(new DependencyResolutionLocatorKey(typeToBuild, idToBuild));
}
return item;
}
private void BuildRepeatedItem(Type typeToBuild, Type typeToRegisterAs, string idToBuild, object item)
{
locator.Add(new DependencyResolutionLocatorKey(typeToRegisterAs, NormalizeID(idToBuild)), item);
}
And, to assure compability with the existing methods:
private TItem Build(Type typeToBuild, string idToBuild, object item)
{
return Build(typeToBuild, typeToBuild, idToBuild, item);
}
Now, all I needed was to add the new methods to add elements:
public void Add(Type typeToRegisterAs, TItem item)
{
Add(typeToRegisterAs, item, null);
}
public void Add(Type typeToRegisterAs, TItem item, string id)
{
Guard.ArgumentNotNull(item, "item");
Guard.TypeIsAssignableFromType(typeof(TItem), typeToRegisterAs, "typeToBuild");
Build(typeToRegisterAs, item.GetType(), id, item);
}
public void Add<TTypeToRegisterAs>(TTypeToRegisterAs item)
where TTypeToRegisterAs : TItem
{
Add<TTypeToRegisterAs>(item, null);
}
public void Add<TTypeToRegisterAs>(TTypeToRegisterAs item, string id)
where TTypeToRegisterAs : TItem
{
Guard.ArgumentNotNull(item, "item");
Build(item.GetType(), typeof(TTypeToRegisterAs), id, item);
}
public TItem AddNew(Type typeToBuild, Type typeToRegisterAs)
{
Guard.TypeIsAssignableFromType(typeToBuild, typeToRegisterAs, "typeToBuild");
return AddNew(typeToBuild, typeToRegisterAs, null);
}
public TItem AddNew(Type typeToBuild, Type typeToRegisterAs, string id)
{
Guard.TypeIsAssignableFromType(typeToBuild, typeof(TItem), "typeToBuild");
Guard.TypeIsAssignableFromType(typeToBuild, typeToRegisterAs, "typeToRegisterAs");
return Build(typeToBuild, typeToRegisterAs, id, null);
}
public TTypeToBuild AddNew<TTypeToBuild, TTypeToRegisterAs>()
where TTypeToRegisterAs : TItem
where TTypeToBuild : TTypeToRegisterAs
{
return (TTypeToBuild)Build(typeof(TTypeToBuild), typeof(TTypeToRegisterAs), null, null);
}
public TTypeToBuild AddNew<TTypeToBuild, TTypeToRegisterAs>(string id)
where TTypeToRegisterAs : TItem
where TTypeToBuild : TTypeToRegisterAs
{
return (TTypeToBuild)Build(typeof(TTypeToBuild), typeof(TTypeToRegisterAs), id, null);
}