【问题标题】:Can parameters be generically accessed?参数可以通用访问吗?
【发布时间】:2011-01-25 10:29:24
【问题描述】:

我有很多看起来像这样的函数。每个都有 N 个参数,每个都创建一个 SQLparamater 数组,每个参数都具有这种非常相似的形式。

[WebMethod]
public static string accessServer(string dataField1, string dataField2, string dataField3) {
    string value;
    SQLParamater[] param = new SQLParameter[len] // len is the amount of arguments
    param[0] = new SQLParameter("@dataField1", dataField1);
    param[1] = new SQLParameter("@dataField2", dataField2);
    param[2] = new SQLParameter("@dataField3", dataField3);
    ...

    // do something with param

    return value;
}

这看起来可以通过使用反射和以通用方式访问参数的组合来通用地完成。

理想的形式是方法

public static SQLParamater[] getParams(someType paramaters)

SQLParamater[] param = getParams(...)

我不确定如何通用地传递所有参数。

[编辑]

请注意,这些数据字段的名称很重要。它不仅仅是一个字符串数组,而是一组键/值对。

[/编辑]

【问题讨论】:

  • 正确的拼写是param_e_ter。
  • 您是想通用添加参数还是想以某种方式访问​​参数?

标签: c#


【解决方案1】:

您可以使用带有可变参数的函数:name(params string[] arguments),因此您可以调用,例如:name(arg1,arg2,arg3,arg4);

【讨论】:

  • 这不是一个选项,因为参数需要有键和值。 IE。参数的名称很重要,而不仅仅是值。
  • 为什么不创建结构名称/值,并将其作为可变参数数组接受?
  • 因为它是一种网络方法(这恰好是重要的信息),我想我坚持使用 String 值。
  • 在参数名称上使用一些约定?
  • 命名约定可能不是最好的方法,因为我想保持数据库的可读性。
【解决方案2】:

之前有人问过这个问题(虽然找不到那个问题),但问题是虽然您可以使用反射MethodBase.GetCurrentMethod() 找出参数名称,但您无法将这些名称与参数值一起压缩因为您无法访问值的参数列表。

还有其他方法可以尝试解决这个非常具体的烦人问题,但我不建议这样做,它没有多大意义。

现在,给定一个这样的方法:

static void SomeMethod(string arg1, int arg2, object arg3)
{
}

你可以这样做:

static void Main()
{
    var b = 123;
    // this now becomes necessary as it's the only way of getting at the metadata 
    // in a presumable safe manner
    Expression<Action> x = () => SomeMethod("a", b, "a" + b); 
    var args = GetArgs(x);
    foreach (var item in args)
    {
        Console.WriteLine("{0}: {1}", item.Key, item.Value);
    }
}

并像这样实现 GetArgs 方法(您仍然需要一种将这些值放在某处的方法,因为调用永远不会发生):

static IDictionary<string, object> GetArgs(Expression<Action> x)
{
    var args = new Dictionary<string, object>();
    var m = (MethodCallExpression)x.Body;
    var parameters = m.Method.GetParameters();
    for (int i = 0; i < m.Arguments.Count; i++)
    {
        // an easy way of getting at the value, 
        // no matter the complexity of the expression
        args[parameters[i].Name] = Expression
            .Lambda(m.Arguments[i])
            .Compile()
            .DynamicInvoke();
    }
    return args;
}

您从编译器创建的表达式树中推断出名称/值对的集合,这是可行的,但有点奇怪。

【讨论】:

  • 我想你的意思是this question
  • @Oliver - 不,这完全是另外一回事。
【解决方案3】:

如果你需要这个,我认为你的 API 设计有缺陷,你最好有一个方法,它接受某种集合。

这样的代码重复几乎从来都不是完成工作的正确方法。

编辑

主题:

我猜你可以从堆栈中获取值:http://www.thescarms.com/dotnet/StackFrame.aspx

【讨论】:

  • 如果我不受 WebMethods 工作方式的限制,我会这样做
  • 您是否尝试从堆栈中提取值?
  • 事实证明我可以通过 Ajax 从客户端传递非本地类型,例如 Dictionary。您正确的问题是一一传递参数。
  • I guess you can get the values from the stack 没有获取堆栈的值,只是获取当前正在执行的方法。这通常通过调用MethodBase.GetCurrentMethod 来实现。该链接对于何时可用的信息也是错误的。包含符号的 PDB 文件也可以在发布版本中加载。
【解决方案4】:

我们这样做:

var dict=new Dictionary
            { 
               {"@param1",value1},
               {"@param2",value2},
               {"@param3",value3},
               {"@param4",value4},
               ....
            };

 DALayer.ExecuteProc("procName",dict);

ExecuteProc 函数中,您可以遍历Dictionary 对象并使用KeyValuePair 对象设置参数。但是,如果您必须为参数设置数据类型、长度等,那么您必须做更多的工作,例如准备 sql 命令来查询参数或传递更复杂的对象作为包含数据类型、长度和方向等信息的参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    • 2016-01-20
    相关资源
    最近更新 更多