Paulo Morgado

.NET Development & Architecture

This Blog

Syndication

Search

Tags

News

Unit Test Today! Get Typemock Isolator!

Projects

Books

 

Visitors

Visitor Locations

Community

Email Notifications

Archives

Profile

Disclaimer

The opinions and viewpoints expressed in this site are mine and do not necessarily reflect those of Microsoft, my employer or any community that I belong to. Any code or opinions are offered as is. Products or services mentioned are purchased by me, made available to me by my employer or the manufacturer/vendor which doesn't influence my opinion in any way.

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);
}

Published Sun, Oct 22 2006 22:45 by Paulo Morgado

Comments

# re: Enhancing CAB's ManagedObjectCollection@ Thursday, April 19, 2007 7:47 AM

Wow, this proved invaluable for my project that relies on interfaces heavily. At least I can use Dependency attributes like they're supposed to work.

Much appreciated stuff!

Inferis

# re: Enhancing CAB's ManagedObjectCollection@ Thursday, April 19, 2007 3:15 PM

That's why I opened an issue when they moved to CodePlex:

http://www.codeplex.com/smartclient/WorkItem/View.aspx?WorkItemId=7307

If you found it usefull, vote on it.

Paulo Morgado

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: