6

私はオンライン予約サイト (航空会社) に取り組んでおり、ユーザー/顧客が選択したルートがいくつかの設定に従って有効かどうかを検証したいと考えています。既存のコードは多くの列挙型を使用しており、特定の列挙型を実行したい特定のアクションにマップするために、多くの if/if else/else を実行していることに気付きました。What I want to do is to write a enum-specific method that would do the mapping for me. Is there any standard way to do this?

これは、実際のアプリと同じクラス名/列挙値などを使用したアプリ コードの簡略化されたバージョンです。

// real app has 9 members, shortened for simplicity's sake
public enum RegionType
{
    Station,
    Country,
    All
}

public enum Directionality
{
    Between,
    From,
    To
}

// simplified version
public class Flight
{
     public RegionType RegionType { get; set; }
     public RegionType TravelRegionType { get; set; }
     public string RegionCode { get; set; }
     public string TravelRegionCode { get; set; }
     public string RegionCountryCode { get; set; }
     public string TravelRegionCountryCode { get; set; }
     public Directionality Directionality { get; set; }
}

使用例を次に示します。

    // valid flight
    Flight flight = new Flight()
    {
        RegionCode = "NY",
        CountryCode = "JP",
        RegionType = RegionType.Station,
        TravelRegionType = RegionType.Country,
        Directionality = Directionality.Between
    };

    // these are the station code/country code that user selected
    // needs to be validated against the Flight object above
    var userSelectedRoutes = new List<KeyValuePair<string, string>>() 
    { 
        new KeyValuePair<string, string>("NY", "JP"),
        new KeyValuePair<string, string>("NY", "AU"),
        new KeyValuePair<string, string>("JP", "NY")
    };

ネストされた if/else if/else 列挙型の一致を減らすために私が書いたいくつかのコード検証:

private bool IsRouteValid(Directionality direction, string origin, 
                          string destination, string departure, string arrival)
{
    // both departure station and arrival station
    if (direction == Directionality.Between)
    {
        return (origin.Equals(departure, StringComparison.OrdinalIgnoreCase) 
          && destination.Equals(arrival, StringComparison.OrdinalIgnoreCase)
               || origin.Equals(arrival, StringComparison.OrdinalIgnoreCase) 
          && destination.Equals(departure, StringComparison.OrdinalIgnoreCase));
    }
    else if (direction == Directionality.From)
    {
            return (origin.Equals(departure, 
                    StringComparison.OrdinalIgnoreCase));   
    }
    else if (direction == Directionality.To)
    {
            return (destination.Equals(arrival, 
                    StringComparison.OrdinalIgnoreCase));
    }

    return false;
}

そして、ここに私が変更したい厄介なコードがあります:

if (flight.RegionType == RegionType.Station 
    && flight.TravelRegionType == RegionType.Country)
{
     return userSelectedRoutes.Any(route => 
            IsRouteValid(flight.Directionality, route.Key, route.Value,
            flight.RegionCode, flight.TravelRegionCode));
}
else if (flight.RegionType == RegionType.Country 
&& flight.TravelRegionType == RegionType.Station)
{
    return userSelectedRoutes.Any(route => 
           IsRouteValid(flight.Directionality, route.Key, route.Value,
           flight.CountryCode, flight.RegionCode));
}
else if (flight.RegionType == RegionType.Station 
&& flight.TravelRegionType == RegionType.Station)
{
    return userSelectedRoutes.Any(route => 
           IsRouteValid(flight.Directionality, route.Key, route.Value,
                       flight.RegionCode, flight.TravelRegionCode));
}
else if (flight.RegionType == RegionType.Station 
&& flight.TravelRegionType == RegionType.All)
{
    return userSelectedRoutes.Any(route => 
           IsRouteValid(flight.Directionality, route.Key, route.Value,
                       flight.RegionCode, route.Value));
}
else if (flight.RegionType == RegionType.All 
&& flight.TravelRegionType == RegionType.Station)
{
    return userSelectedRoutes.Any(route =>
           IsRouteValid(flight.Directionality, route.Key, route.Value,
           route.Key, flight.TravelRegionCode));
}
else if (flight.RegionType == RegionType.All 
        && flight.TravelRegionType == RegionType.All)
{
    return true;
}
else
{
    return false;
} 

伝説:

RegionCode= 出発駅/出発
TravelRegionCode地 = 到着駅/目的地
Between= ルートは、指定された出発駅と到着駅からのみである必要があり、その逆 (例: NY-JP または JP-NY)
From= 特定の駅から任意のルート (例: AU- All )
To= 特定の駅への任意のルート (例: All -AU)

お気.Any付きのように、上記の条件はすべて同じですが、若干の変更があります。可能であれば、コードの冗長性を減らしたいです。使用KeyValuePairしたので、単一のデータ型に出発駅と到着駅の両方があります。

このコードの煩雑さ/美しさを軽減する方法についてのアイデアはありますか? 私もハードコーディングしたことは知っていますが、可能な組み合わせは3つしかないIsRouteValid()ことは100%確信しています。一方、Station-Station、Station-Country、Country-Station、Country-Country などのいくつかの組み合わせを持つことができます。DirectionalityRegionType

期待される出力:

最初のルート (NY-JP) で有効/真
2 番目のルート (NY-AU) で無効/偽
3 番目のルート (JP-NY) で有効/DirectionalityBetween

この非常に長いクエリをお読みいただきありがとうございます。また、フィードバックと提案をお寄せいただきありがとうございます。

類似の投稿:

列挙型と辞書

4

2 に答える 2

20

このような列挙型アクションマッピングを処理する方法は、辞書を使用することです。次に例を示します。

public enum MyEnum
{
    EnumValue1,
    EnumValue2,
    EnumValue3
}

private IDictionary<MyEnum, Action> Mapping = new Dictionary<MyEnum, Action>
    {
        { MyEnum.EnumValue1, () => { /* Action 1 */ } },
        { MyEnum.EnumValue2, () => { /* Action 2 */ } },
        { MyEnum.EnumValue3, () => { /* Action 3 */ } }
    };

public void HandleEnumValue(MyEnum enumValue)
{
    if (Mapping.ContainsKey(enumValue))
    {
        Mapping[enumValue]();
    }
}

もちろん、パラメータを処理するFunc代わりにを使用することもできActionます。

編集:

1つの列挙型だけでなく、列挙型のペアも使用しているため、上記の例を調整してTuple、列挙型の値を集計するための何らかの方法を処理する必要があります。

于 2013-01-18T08:57:44.630 に答える