我正在尝试删除具有可变数量参数的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参数?
答案 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