从字符串方法名称调用方法

时间:2017-03-01 20:22:50

标签: c# reflection

我有两套Urls,一套用于PreProd,另一套用于Prod。每个Url都有几个API节点。我没有硬编码这些API节点,而是将它们保存在枚举

这样的事情:

//Prod
private enum Prod
{
    precheckorder,
    submitresubmit,
    creditInquiry,
    createupdateorder,
    confirmorder,
    getorderstatus,
    cancelorder,
}

/// <summary>
/// Gets the relative URL.
/// </summary>
/// <param name="u">The u.</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
private static string GetRelativeUrl(Prod u)
{
    switch (u)
    {
        case Prod.precheckorder:
            return "https://contesa.tex.com/api/precheckorder";
        case Prod.submitresubmit:
            return "https://contesa.tex.com/api/submitresubmit";
        case Prod.creditInquiry:
            return "https://contesa.tex.com/api/creditinquiry";
        case Prod.createupdateorder:
            return "https://contesa.tex.com/api/createupdateorder";
        case Prod.confirmorder:
            return "https://contesa.tex.com/api/confirmorder";
        case Prod.getorderstatus:
            return "https://contesa.tex.com/api/getorderstatus";
        case Prod.cancelorder:
            return "https://contesa.tex.com/api/cancelorder";
        default:
            // Handle bad URL, possibly throw
            throw new Exception();
    }
}

我们使用环境变量来存储环境名称,这就是决定使用哪个API集的原因。

理想情况下,我希望有一个方法,我传入我的环境和api名称,它将返回API Url。

这样的东西
GettexApiUrlBasedOnEnvironment("Dev", "precheckorder");

并且回复将是

"https://contoso.tex.com/api/precheckorder"

任何想法/建议将不胜感激。 TIA

3 个答案:

答案 0 :(得分:2)

只需将您的网址存储在一个字典中,如下所示:

public enum ApiType
{
    precheckorder,
    submitresubmit,
    creditInquiry,
    createupdateorder,
    confirmorder,
    getorderstatus,
    cancelorder,
}

 public enum EnvironmentType {
    Dev,
    Prod
}

public static string GettexApiUrl(ApiType apiType) {
    var envRaw = Environment.GetEnvironmentVariable("YourVariable");
    EnvironmentType env;
    if (!Enum.TryParse(envRaw, out env))
        throw new Exception("Invalid environment provided in environment variable YourVariable: " + envRaw);
    return GettexApiUrlBasedOnEnvironment(env, apiType);
}

public static string GettexApiUrlBasedOnEnvironment(EnvironmentType env, ApiType apiType) {
    if (!_urls.ContainsKey(env))
        throw new Exception("Invalid environment " + env);
    var url = _urls[env];
    if (!url.ContainsKey(apiType))
        throw new Exception("Invalid api type " + apiType);
    return url[apiType];
}

private static readonly Dictionary<EnvironmentType, Dictionary<ApiType, string>> _urls = new Dictionary<EnvironmentType, Dictionary<ApiType, string>>(
    ) {
    {EnvironmentType.Dev, new Dictionary<ApiType, string>() {
        {ApiType.precheckorder,  "https://contoso.tex.com/api/precheckorder"},
        // etc
    } }, {
        EnvironmentType.Prod, new Dictionary<ApiType, string>() { 
        {ApiType.precheckorder,  "https://contesa.tex.com/api/precheckorder"},
    }},
}; 

答案 1 :(得分:1)

尝试下面的代码,没有其他词典,enum,切换\案例等

private static string GettexApiUrlBasedOnEnvironment(string envType, string api)
{
            string env = envType.Equals("Dev") ? "contoso" : "contesa";
            return $"http://{env}.tex.com/api/{api}";
}

这很简单,在新API的情况下无需维护。

答案 2 :(得分:1)

你也可以使用反射,并使用如下字符串表示来获取枚举的类型和值:

using System;
using System.Reflection;

namespace EnumGames
{
    public class Program
    {
        static void Main(string[] args)
        {
            SomeClass sc = new SomeClass();
            var ans = sc.GetEnumValue("MyEnum", "OptionB");
        }
    }

    public class SomeClass
    {
        public enum MyEnum
        {
            OptionA,
            OptionB,
            OptionC
        }
        public enum MyOtherEnum
        {
            OptionA,
            OptionB,
            OptionC
        }
        public string GetEnumValue(string enumNameString, string enumOptionString)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var enumType = assembly.GetType($"{this.ToString()}+{enumNameString}");
            var enumOption = Enum.Parse(enumType, enumOptionString);
            return GetEnumValue(enumOption);
        }
        private string GetEnumValue(object enumOption)
        {
            if (enumOption is MyEnum)
            {
                switch ((MyEnum)enumOption)
                {
                    case MyEnum.OptionA:
                        return "Hi";
                    case MyEnum.OptionB:
                        return "Hello";
                    case MyEnum.OptionC:
                        return "Yo";
                    default:
                        return "Nope";
                }
            }
            else if (enumOption is MyOtherEnum)
            {
                switch ((MyOtherEnum)enumOption)
                {
                    case MyOtherEnum.OptionA:
                        return "Bye";
                    case MyOtherEnum.OptionB:
                        return "Ta-Ta!";
                    case MyOtherEnum.OptionC:
                        return "Goodbye";
                    default:
                        return "Nopee";
                }
            }
            return "Nooope";
        }
    }
}

在上面的示例中,GetEnumValue()接收枚举名称和选项,将其转换为真实的枚举选项,然后使用其他方法获取所需的值。

所以,通过调用

GetEnumValue("MyEnum", "OptionB");

我会收到字符串"Hello"

通过致电

GetEnumValue("MyOtherEnum", "OptionB");

我会收到字符串"Ta-Ta!"