views:

137

answers:

3

Hi

How could I make this code more generic in the sense that the Dictionary key could be a different type, depending on what the user of the library wanted to implement? For example someone might what to use the extension methods/interfaces in a case where there "unique key" so to speak for Node is actually an "int" not a "string" for example.

public interface ITopology
{
    Dictionary<string, INode> Nodes { get; set; } 
}

public static class TopologyExtns
{
    public static void AddNode(this ITopology topIf, INode node)
    {
        topIf.Nodes.Add(node.Name, node);
    }
    public static INode FindNode(this ITopology topIf, string searchStr)
    {
        return topIf.Nodes[searchStr];
    }
}

public class TopologyImp : ITopology
{
    public Dictionary<string, INode> Nodes { get; set; }

    public TopologyImp()
    {
        Nodes = new Dictionary<string, INode>();
    }
}
+2  A: 
public interface ITopology<T>
{
    Dictionary<T, INode> Nodes { get; set; } 
}

public static class TopologyExtns<T>
{
    public static void AddNode<T>(this ITopology<T> topIf, T key, INode node)
    {
        topIf.Nodes.Add(key, node);
    }
    public static INode FindNode<T>(this ITopology<T> topIf, T searchKey)
    {
        return topIf.Nodes[searchKey];
    }
}

public class TopologyImp<T> : ITopology<T>
{
    public Dictionary<T, INode> Nodes { get; set; }

    public TopologyImp()
    {
        Nodes = new Dictionary<T, INode>();
    }
}
derek
TopologyExtns is wrong - ITopology is now generic, and you need to either make the extension method generic or the parameter reference specific.
Matt Jordan
thanks @Matt, good catch.
derek
+2  A: 

Why not make your Topology Interface generic? I'm a little fuzzy on the extension methods myself, but this should be workable.

public interface ITopology<TKey> 
{ 
    Dictionary<TKey, INode> Nodes { get; set; }  
} 

public static class TopologyExtns 
{ 
    public static void AddNode<T>(this ITopology<T> topIf, T key, INode node) 
    { 
        topIf.Nodes.Add(key, node); 
    } 
    public static INode FindNode<T>(this ITopology<T> topIf, T searchObj) 
    { 
        return topIf.Nodes[searchObj]; 
    } 
} 


public class TopologyImp : ITopology<String> 
{ 

public TopologyImp() 
{ 
    Nodes = new Dictionary<String, INode>(); 
} 
}
Matt Jordan
+6  A: 

Make the interface generic, then use a Func<INode,T> as a selector for the key. This assumes that you want the key for the dictionary to be extracted from the node. If this isn't a hard requirement, then you could specify the key itself using the generic type specifier in the signature.

public interface ITopology<T>
{ 
    Dictionary<T, INode> Nodes { get; set; }  
} 

public static class TopologyExtns 
{ 
    public static void AddNode<T>(this ITopology<T> topIf, INode node, Func<INode,T> keySelector ) 
    { 
        topIf.Nodes.Add( keySelector(node), node ); 
    } 
    public static INode FindNode<T>(this ITopology<T> topIf, T searchKey ) 
    { 
        return topIf.Nodes[searchKey]; 
    } 
} 

public class TopologyImp<T> : ITopology<T> 
{ 
    public Dictionary<T, INode> Nodes { get; set; } 

    public TopologyImp() 
    { 
        Nodes = new Dictionary<T, INode>(); 
    } 
}

You might also consider making INode a generic type. That would allow you to specify the Key as a property of the generic type which the implementation could defer to the appropriate "real" key. This would save you from having to supply either the key or a selector for the extension method.

Alternative:

public interface INode<T>
{
     T Key { get; }
     string Name { get; set; }
     int ID { get; set; }
}

public class StringNode : INode<string>
{
    public string Key { get { return this.Name; } }
    public string Name { get; set; }
    public int ID { get; set; }
}

public interface ITopology<T> 
{  
    Dictionary<T, INode<T>> Nodes { get; set; }   
}  

public static class TopologyExtns  
{  
    public static void AddNode<T>(this ITopology<T> topIf, INode<T> node )  
    {  
        topIf.Nodes.Add( node.Key, node );  
    }  
    public static INode<T> FindNode<T>(this ITopology<T> topIf, T searchKey )  
    {  
        return topIf.Nodes[searchKey];  
    }  
}  

public class TopologyImp<T> : ITopology<T>  
{  
    public Dictionary<T, INode<T>> Nodes { get; set; }  

    public TopologyImp()  
    {  
        Nodes = new Dictionary<T, INode<T>>();  
    }  
}

Used as:

var topology = new TopologyImp<string>();
topology.AddNode( new StringNode { Name = "A", ID = 0 }  );
var node = topology.FindNode( "A" );
tvanfosson