简体   繁体   中英

Get number of parameters passed to a method?

Is it possible to get the number of parameters being passed to a method in run time, and if so how?

For instance, if if would be possible, I could have a database interaction method as follows,

public void AddSomethingToDatabase(string parameter1, string parameter2)
{
   ...
   foreach(param in parameters)
   {
      sp.AddParameter(GetName(param),param));
   }
   conn.Execute(...);
}

I am attempting to not have to add/change a line in code each time my stored procedure parameters change, instead only changing the method signature with the correct stored procedure parameters. In this case, parameter1 and parameter2 would be the actual names of the parameters in the stored procedure. Any ideas?

没有反思:

public int AddSomethingToDatabase(params object[] parameters)

Can you pass the parameters as a collection? This way it is unlimited and easy to use. This is how I do it for my own projects

public void AddSomethingToDatabase(Dictionary<string, object> parameters)
{
   foreach(KeyValuePair<string, object> param in parameters)
   {
      string paramname = param.Key;
      object paramvalue= param.Value;
      sp.AddParameter(paramname, paramvalue);
   }
   conn.Execute(...);
}

EDIT : I'd like to clarify more how I used this method in my own programs.

I specify the database procedure parameters in the method itself, and pass the parameters like you do. I do realise there is a better way, like using DTO's

public void AddSomethingToDatabase(string param1, int param2)
{
   Dictionary<string, object> parameters = new Dictionary<string, object>();
   parameters.Add("pID", param1);
   parameters.Add("pName", param2);

   ModifyDatabase(parameters, "update_myTable");
}

public void ModifyDatabase(Dictionary<string, object> parameters, string procedure)
{
   // Do necessary checks on parameters here
   // Check database availability
   // And many other checks that would be recurring for every database transaction
   // ... that's why I have them all in one place. Executing Queries is the same
   // ... every time. Why would you write the error handling twice? :-)

   // Loop parameters and fill procedure parameters

   // Execute the lot
}
Console.WriteLine(MethodInfo.GetCurrentMethod().GetParameters()[0].Name);

Will write the name of the first parameter to the current method.

As for getting the value, it seems reflection doesn't have this.

public class NameValue
{
    public NameValue(string name, object value)
    {
        Name = name;
        Value = value;
    }
    public string Name { get; set; }
    public object Value { get; set; }
}

private void DoSomething(params NameValue[] args)
{
    foreach (var nameValue in args)
    {
        //sp.AddParameter(nameValue.Name, nameValue.Value);
    }
}

private void GenerateTable(Table table)
{
    DoSomething(new NameValue("name", "Jonas"), new NameValue("Age", 99));
}

If 3rd-party component is an option, looks like BLToolkit would do exactly what you expect.

Call definition for the stored procedure in your code will look like in the snippet below and post-processed by BLT to pass all parameters to the sproc (by default it expects same names in sproc and method signature).

[SprocName("sp_MySproc")]
public abstract void CallMySproc(string @parameter1, string @parameter2); 

There are more detailed code examples in unit tests.

As a disclaimer, BLT supports it, but I didn't use it with Mono myself.

Edit: BLT source code is available and might help with the question, but its implementation idea is somewhat different from yours. Instead of using reflection on each call, it does it only when class is used for the first time, implements declared abstract method, and after that point there is no performance downgrade.

I don't think you can get the parameter values, even with reflection. If you don't reference them specifically in the method body, the compiler will just optimise them away. See these posts for example: Can I get parameter names/values procedurally from the currently executing function?

public class SPParamCollection : List<SPParams>{ }
public struct SPParams
{
    public string Name { get; set; }
    public object   Value { get; set; }
    public SqlDbType SqlDbType { get; set; }
}
public void AddSomethingToDatabase(SPParamCollection arrParam)
{
    foreach (SPParams param in arrParam)
        cmd.Parameters.Add(param.Name, param.Value);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM