嵌套泛型类型:重用外部类型参数

时间:2014-07-11 16:43:12

标签: c# generics

我正在尝试删除具有可变数量参数的System.Func集合的重复代码。 (这用于允许代码“挂钩”到其他组件的逻辑中。) 所以我试图删除几个几乎相同的方法,改为使用泛型方法。

为了使其工作,我将它们包装在HookContainer类中,并使其实现了一个通用接口。

public interface IHookContainer
{
    void Add<TFunc> (string filterName, int priority, KeyValuePair<string, TFunc> action);
}

public class HookContainer<T>:IHookContainer
{
    Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();

    public void Add<T> (string filterName, int priority, KeyValuePair<string, T> action)
    {
         // Add an item to the Dictionary
    }
}

这允许我将它们全部放在一个可以使用Type

访问的Dictionary中
Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
    typeof(HookContainer<System.Func<object,object>>),new HookContainer<System.Func<object,object>>()
},
// More dictionary entries like this (with more parameters)
};


    public string AddFilter<T> (string filterName, T action, string filterTag = null, int priority=0)
    {

            KeyValuePair<string, T> data = new KeyValuePair<string, T> (filterTag, action);
            if (containers.ContainsKey (typeof(T))) {
                    IHookContainer container = containers [typeof(T)];
                    container.Add<T> (filterName, dictPriority, data);


            }

            return filterTag;

    }

现在我收到编译错误说:

cannot convert `System.Collections.Generic.KeyValuePair<string,T>' 
expression to type `System.Collections.Generic.KeyValuePair<string,T>'

所以显然缺少一些我认为理所当然的信息。或者我在想错。或两者。 为什么它不能将类型转换为...本身??

如果实现了接口,我显然不能使用Generic类中的相同Type参数作为泛型方法。可悲的是,这种类型也无法推断。有没有办法让这项工作?

还有一个警告,即类型参数名称与外部类型参数相同。我可以告诉编译器这完全是为了吗?

感谢您的帮助。我正在使用C#4.0

更新

我可以通过使用第二个Type参数声明HookContainer并使用它将其传递到Add方法来获取代码。

现在看起来像这样:

public class HookContainer<T,U>:IHookContainer
{
    Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();
    public void Add<U> (string filterName, int priority, KeyValuePair<string, T> action)
    {
        // Add an item to the Dictionary
    }

}

这当然要求我在声明字典时冗余地传递容器的类型两次:

Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
typeof(HookContainer<System.Func<object,object>,System.Func<object,object>>),new HookContainer<System.Func<object,object>,System.Func<object,object>>()
}
};

所以尽管这可能有效,但它看起来和感觉都很荒谬。有没有办法(重新)使用单个Type参数?

2 个答案:

答案 0 :(得分:2)

<强>更新

我误解了你的问题。你实现这个的方式,不是你想要的。界面中的声明与实现中的声明不同。 在您的接口声明中,您指定此接口的实现应具有泛型函数(可以使用各种类型调用)。在您的实现中,您希望将此限制为您在类中指定的类型。 类实现将针对一种特定类型。

即。 IHookContainer接口指定您可以使用int,string等调用Add函数。而在HookContainer<string>中,您只能使用字符串参数调用Add

更适合您想要的实现,但您不能将其存储在Dictionary中:

public interface IHookContainer<T>
{
   Add(string filterName, int priority, KeyValuePair<string, T> action);
}

解决方案是什么(我可能做的)是将Dictionary更改为List并创建一个检索正确IHookContainer<T>的函数。或者在项目数量很大时保留字典,并按键解决正确的字典。

private List<object> containers = new List<object>();
private IHookContainer<T> GetCorrectHookContainer<T>()
{
    // might need to add when not available?
    return containers.OfType<IHookContainer<T>>().FirstOrDefault();
}

你的AddFilter函数将是这样的(伪代码)

public void AddFilter<T>(...)
{
    GetCorrectHookContainer<T>().Add(...);
}

<强>旧

因为您在函数中指定了类型参数(再次),所以该类的T与函数中的T不同。泛型函数中的T参数'隐藏'类的T。你可以使用它。您不必在函数中指定它。您的实施可以是:

public void Add(string filterName, int priority, KeyValuePair<string, T> action)
{
     // Add an item to the Dictionary
}

使用示例:

var x = new HookContainer<int>();
x.Add("test", 1, new KeyValuePair<string,int>("test", 4)); 

答案 1 :(得分:1)

问题似乎来自TFrom Add而来自T的{​​{1}}是两种不同的泛型类型。

我不知道是否可行,但我会使用C的主要签名HookContainer而不是(int argc, char[] argv)函数:

Func