不知道以前是否有人问过这个问题,所以如果有,请给我另一个问题。
我有一个这样的方法:
private void SomeMethod<TLocation>(int x, int y) where TLocation : DataLocation
{
//
}
在我想用它调用的方法中,我有一个枚举,我想用type参数调用该方法。
public enum LocationType
{
Country,
State,
County,
City,
Neighborhood,
Street
}
数据定位类型:
DataCountry
DataState
DataCounty
DataCity
DataNeighborhood
DataStreet
知道类型参数是"Data"+枚举名,有什么方法可以动态调用我的方法吗?
或者我应该坚持:
switch (locationType)
{
case LocationType.Country:
SomeMethod<DataCountry>(1, 2);
break;
case LocationType.State:
SomeMethod<DataState>(2, 4);
break;
// etc
}
编辑:
看来只有反思。我会坚持开关。
以下是可能的解决方案:
var dispatches = new Dictionary<LocationType, Action<int, int>>();
dispatches.Add(LocationType.Country, SomeMethod<DataCountry>);
dispatches.Add(LocationType.State, SomeMethod<DataState>);
//... and etc.
dispatches[LocationType.Country](1, 2); // the same as SomeMethod<DataCountry>(1,2)
我认为您应该坚持使用switch语句建议的实现。它清晰简洁,而且我不知道你如何动态地做到这一点。
您总是可以重构您的开关用例,并将特定于用例的代码放在单独的函数中。这是一篇关于它的好文章——http://elegantcode.com/2009/01/10/refactoring-a-switch-statement/
听起来这个方法应该被定义为DataState类的一个成员,并相应地重写,可能在内部使用this.GetType()
。你在这里有点滥用泛型。
也就是说。。。(我几乎希望我被否决了…)
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
new ResolveIt<LocationType>().InvokeIt(LocationType.State, 1, 5);
Console.ReadLine();
}
}
public class ResolveIt<TEnum> // Unfortunately can't constrain on enums
{
private static readonly Action<int, int>[] Actions
= Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Select(v => typeof(ResolveIt<TEnum>)
.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
.First(n => n.Name == "SomeMethod")
.GetGenericMethodDefinition()
.MakeGenericMethod(new[] { Type.GetType(typeof(ResolveIt<TEnum>).Namespace + ".Data" + Enum.GetName(typeof(TEnum), v)) }))
.Select(mi => (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>), mi))
.ToArray();
public void InvokeIt(TEnum type, int x, int y)
{
Actions[(Int32)Convert.ChangeType(type, typeof(Int32))](x, y);
}
private static void SomeMethod<TLocation>(int x, int y) where TLocation : DataLocation
{
Console.Out.WriteLine(typeof(TLocation));
}
}
public enum LocationType { Country, State, City, Zip, }
public class DataLocation { }
public class DataCountry:DataLocation { }
public class DataState:DataLocation { }
public class DataCity:DataLocation { }
public class DataZip:DataLocation { }
}