interfaces generics and collections question

interfaces generics and collections question

Old forum URL: forums.lhotka.net/forums/t/4651.aspx


rkelley posted on Wednesday, April 09, 2008

I have three sets of objects with child objects:

Action --> ActionParts --> ActionPart

ServiceTask -->TaskParts --> TaskPart

ServiceOrderTask --> ServiceOrderTaskParts --> ServiceOrderTaskPart

All of the main classes implement iActionTask interface which sets up the common properties that they all have in common.

The problem I am running into is that I have some methods that need to access those properties, which works fine, however I also need to retrieve part information from their child objects. My first thought was to create an interface for the collection and an interface for the child object and that would solve the problem. So this is what I did:

 

public interface iActionTask
{
        iActionTaskParts Parts
        {
            get;
        }
}

public interface iActionTaskParts
{

}

public interface iActionTaskPart
    {
        string PartNumber
        {
            get;
            set;
        }

        string PartDescription
        {
            get;
            set;
        }

        double Quantity
        {
            get;
            set;
        }
}

This all seemed fine except, the interface iActionTaskParts does not know that it is a collection or what type of objects it contains. So back to the drawing board with this:

 

    public interface iActionTaskParts 
        where T : iActionTaskParts
        where C : iActionTaskPart
    {

    }

But this gives me errors because:

iActionTaskParts Parts
        {
            get;
        }

needs to have two Type parameters and I am just stuck. I don't know that generics are the answer so I am hoping somebody smarter than I am can help me out.

tmg4340 replied on Wednesday, April 09, 2008

If all you need to do is get the children, you can add some methods to your interface to get what you need.  Unfortunately, interfaces don't allow for indexers that cast correctly - if you specify an indexer signature, it overrides the collection's indexer - so you have to name your routines something else.

From a bare-bones perspective, you could simply add:

iActionTaskPart GetChild(int index);

to your "iActionTaskParts" interface and call it a day.  However, unless your only access to the collection is by an index value that you know ahead of time, that doesn't get you much.  So, you'll probably want some more properties/methods to get you a collection count, etc.

Having said that, this isn't the route I recommend.  At the end of the day, your "iActionTaskParts" interface is probably going to look a lot like the .NET "IList" interface, so you could just use that.  Or you can go one step further and use the "IList<T>" generic interface, to get the strongly-typed stuff.  So you get rid of your "iActionTaskParts" interface, and your "iActionTask" interface's one method signature looks like this:

IList<iActionTaskPart> Parts { get; }

Implementing that method in your main classes is fairly trivial - just create a "List<iActionTaskPart>" object, fill it with the collection's children, and return it.

(You do have to do it that way, BTW - you can't cast your child collection member, because the CSLA collection classes don't implement "IList<iActionTaskPart>".)

This all works if you don't want to bind based on these base interfaces.  If you need to do that, then you have a whole different problem, and you'll probably want to move away from interfaces and head towards base classes.  But if you just have some routines that need to model a generic parent/child relationship (for example, to do some simple totalling of your "Quantity" values), this should get you there.

HTH

- Scott

rkelley replied on Wednesday, April 09, 2008

Scott,

You are a gentleman and a scholar! This worked great! I used the IList<T> method and it seems to be just the ticket.

Ryan

Copyright (c) Marimer LLC