【发布时间】:2012-02-14 14:59:52
【问题描述】:
我正在尝试更新 Medusa 以允许在其当前使用 List<DbParameter> 的任何地方使用装饰的 POCO。我遇到的问题是调用了错误的重载。这是我所看到的一个简单示例:
void Run()
{
CallDoSomething<Program>("Hello World", new object());
CallDoSomething<Program>("Hello World2", new List<int>());
}
// `DoSomething<T>` represents the functions that do the heavy lifting
public T DoSomething<T>(string someString, List<int> ints) where T : class
{
Console.WriteLine("List<int>: {0}", someString);
return default(T);
}
public T DoSomething<T>(string someString, object ints) where T : class
{
Console.WriteLine("object: {0}", someString);
// In my real implementation, this turns the object to a typed List<T>
// and passes it to the previous overload.
return default(T);
}
// We're trying to refactor the code in this method to reduce code duplication in
// the `CallDoSomething<T>` methods that will actually be called by the end user
internal T CallDoSomething<T, U>(string someString, U ints) where T : class
{
// Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods
return DoSomething<T>(someString, ints);
}
public T CallDoSomething<T>(string someString, List<int> ints) where T : class
{
return CallDoSomething<T, List<int>>(someString, ints);
}
public T CallDoSomething<T>(string someString, object ints) where T : class
{
return CallDoSomething<T, object>(someString, ints);
}
在这种情况下,结果输出是:
object: Hello World
object: Hello World2
虽然我期待它是:
object: Hello World
List<int>: HelloWorld2
这两种情况都指向采用object 参数的重载是有道理的,因为它们都是对象。我怀疑这是因为(据我所知)泛型和重载解析是在编译时而不是运行时处理的。
我想到的第一个选择是使用反射在CallDoSomething<T, U> 中动态调用调用,但感觉太脏了。相反,我提出的解决方案涉及将委托传递给CallDoSomething<T, U>,这似乎可行。这是它的样子:
void Run()
{
CallDoSomething<Program>("Hello World", new object());
CallDoSomething<Program>("Hello World2", new List<int>());
}
public T DoSomething<T>(string someString, List<int> ints) where T : class
{
Console.WriteLine("List<int>: {0}", someString);
return default(T);
}
public T DoSomething<T>(string someString, object ints) where T : class
{
Console.WriteLine("object: {0}", someString);
return default(T);
}
internal delegate T DoSomethingDelegate<T, U>(string someString, U ints) where T : class;
internal T CallDoSomething<T, U>(string someString, U ints, DoSomethingDelegate<T, U> doSomething) where T : class
{
// Do a bunch of stuff here that would otherwise be duplicated by the `CallDoSomething<T>` methods
return doSomething(someString, ints);
}
public T CallDoSomething<T>(string someString, List<int> ints) where T : class
{
return CallDoSomething<T, List<int>>(someString, ints, DoSomething<T>);
}
public T CallDoSomething<T>(string someString, object ints) where T : class
{
return CallDoSomething<T, object>(someString, ints, DoSomething<T>);
}
这似乎有效,它消除了大量的代码重复,但它使代码相当复杂。有没有更好的方法来解决这个问题?
【问题讨论】: