【问题标题】:Passing Many Parameters for API为 API 传递许多参数
【发布时间】:2014-12-11 19:57:39
【问题描述】:

我有一个执行复杂数学分析的 API。该分析目前涉及计算 12 个不同的组件值,但组件值的数量是可变的:它会改变(可能会增加)。组件将被添加,有些可能会被删除。每个组件都需要指定多个参数(每个组件的编号不同)。需要设置所有参数值才能进行分析。

API 通过两个方法调用,每个方法都有一个重载。

方法一:AnaylyzeAll()

此方法利用所有已知组件进行分析,并为所有组件参数使用默认值。

方法一重载:AnaylyzeAll(componentParameters)

此方法利用所有已知组件进行分析,并使用用户指定的值来覆盖指定组件的选择参数的默认值。

方法二:AnaylyzeSelect(componentsToBeAnalyzed)

此方法使用为分析指定的组件,并为所有组件参数使用默认值。

方法二重载:AnaylyzeSelect(componentsToBeAnalyzed, componentParameters)

此方法使用为分析指定的组件,并使用用户值作为指定组件的选择参数的参数。

componentsToBeAnalyzed 是一个用户初始化的列表,如下:

internal readonly List<string> componentsToBeAnalyzed = new List<string>()
{
    "ComponentB",
    "ComponentG",
    "ComponentA"
};

我正在考虑使用 ReadOnlyCollection,但由于我的目标是 .Net 3.5,这可能会增加复杂性。

componentParameters 对象是我的问题。我需要允许用户指定为其提供参数的组件以及参数值。我想出的解决方案是使用匿名类型数组,然后将其转换为列表,然后再将其转换为嵌套字典。

用户提供以下内容,

var componentParameters = new []
{
    new { ComponentName = "ComponentA", ParameterName = "Parameter 1", paramValue = (object)3.247 },
    new { ComponentName = "ComponentA", ParameterName = "Parameter 3", paramValue = (object)"volatile" },
    new { ComponentName = "ComponentA", ParameterName = "Parameter 7", paramValue = (object)Method.Standard },

    new { ComponentName = "ComponentC", ParameterName = "Parameter 2", paramValue = (object)11 },
    new { ComponentName = "ComponentC", ParameterName = "Parameter 5", paramValue = (object)1.145 }
};

在API中,我处理如下

var componentInfo = componentParameters.ToList();
Dictionary<string, Dictionary<string, object>> dict2 = componentInfo
    .GroupBy(x => x.ComponentName)
    .ToDictionary(gComponentName => gComponentName.Key,
                  gComponentName => gComponentName.ToDictionary(t => t.ParameterName,
                                                                t => t.paramValue));

我的问题是,这对我来说看起来不像是干净优雅的代码。我一直在试图弄清楚如何将其重构为更简单、更有效的东西,但一直没能做到。我还想为用户简化参数值的输入方式。我想要类似的东西

var componentParameters2 = new object []
{
    new { name = "ComponentA", param1=3.247, param3 = "volatile", param7 = Method.Standard },
    new { name = "ComponentC", param2 = 11, param5 =1.145 }
};

但我无法将其转换为与上述相同类型的嵌套字典。任何关于如何最好地处理这种情况的建议和建议将不胜感激。

【问题讨论】:

    标签: c# dictionary argument-passing


    【解决方案1】:

    如果你要创建一个代表你的参数的类,例如:

    public class Component
    {
        public string Name { get; set; }
    
        public Dictionary<string, object> Parameters { get; set; }
    
        public object this[string key]
        {
            get
            {
                return this.Parameters[key];
            }
            set
            {
                if(this.Parameters.ContainsKey(key))
                {
                    this.Parameters[key] = value;
                }
                else
                {
                    this.Parameters.Add(key, value);
                }
            }
        }
    }
    

    然后你可以像这样使用它:

    var components = new Component
        {
            Name = "ComponentA"
        };
    
    components["parameter1"] = 123;
    components["parameter2"] = "volatile";
    components["parameter3"] = Method.Standard;
    
    // etc...
    

    也许这有帮助?

    为了解决希望它简洁的语法问题,请尝试在构造函数中使用params关键字。

    public Component(string name, params KeyValuePair<string, object>[] parameters)
    {
        Name = name;
    
        Parameters = new Dictionary<string, object>(parameters);
    }
    

    这将允许以下初始化语法:

    var components = new []
        {
            new Component("ComponentA", new []
                {
                    { "Parameter1", 123 },
                    { "Parameter2", "volatile" },
                    { "Parameter3", Method.Standard },
                },
            new Component("ComponentB", new []
                {
                    { "Parameter5", 12.25 },
                    { "Parameter7", 12 }
                },
        };
    

    【讨论】:

    • 感谢您的建议,但在我的情况下不起作用。首先,我不希望客户端必须创建一个类才能传递参数。其次,更重要的是,客户端可能会从他的一个方法内部调用 API,因此无法在内部创建一个类一个方法。最后,在我看来,这增加了用户的复杂性。
    • 鉴于您的客户听起来有很多规定和用例,您应该在描述中提供这些内容,以便我们更好地为您的问题量身定制解决方案。
    • 没有额外的规定。我只是在寻找一种解决方案——如果可能的话——用户不需要创建类或字典。越简单对用户越好。我确实喜欢你上一篇文章中的初始化语法,即使它仍然需要构造一个类。
    • @PBrenek 在我看来,期望你的用户理解他们必须将一个特殊格式化的匿名类型传递给你的函数比他们必须传递一个已知数量的类或字典要复杂得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    相关资源
    最近更新 更多