基于另一个值创建类型参数



不知道以前是否有人问过这个问题,所以如果有,请给我另一个问题。

我有一个这样的方法:

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 { }
}

最新更新