如何使此代码更通用

时间:2010-05-06 18:16:03

标签: c# generics interface extension-methods

如果Dictionary键可能是一个不同的类型,我怎么能使这个代码更通用,这取决于库的用户想要实现什么?例如,有人可能在使用“唯一键”的情况下使用扩展方法/接口,可以说节点实际上是“int”而不是“字符串”。

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

3 个答案:

答案 0 :(得分:6)

使界面通用,然后使用Func<INode,T>作为密钥的选择器。这假定您希望从节点中提取字典的键。如果这不是一个硬性要求,那么您可以使用签名中的泛型类型说明符指定密钥本身。

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

您可能还会考虑将INode设为通用类型。这将允许您将Key指定为泛型类型的属性,该实现可以遵循相应的“真实”键。这样可以避免为扩展方法提供密钥或选择器。

替代:

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

用作:

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

为什么不将拓扑界面设为通用?我自己对扩展方法有点模糊,但这应该是可行的。

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