Can parameters be generically accessed? - c#

I have a lot of functions that look like this. Each has N arguments and each creates an SQLparamater array with each paramater being of this very similar form.
[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;
}
This looks like it can be done generically using a combination of Reflection and accessing the paramaters in a generic way.
Ideally a method of the form
public static SQLParamater[] getParams(someType paramaters)
and SQLParamater[] param = getParams(...)
I'm not sure how to pass on all the paramaters generically.
[Edit]
Note that the names of these datafields are important. It's not just an array of strings but rather a set of key/value pairs.
[/Edit]

You can use a function with variable arguments: name(params string[] arguments), so you can call, for example: name(arg1,arg2,arg3,arg4);

This has been asked about before (can't find that question though), the problem however is that while you can figure out the parameter names by using reflection MethodBase.GetCurrentMethod() you can't zip those names together with the parameter values because there's no way for you to access a parameter list of values.
There are other ways of trying to work around this very specific tiresome problem but I don't recommend doing it this way, it just doesn't make a lot of sense.
Now, given a method like this:
static void SomeMethod(string arg1, int arg2, object arg3)
{
}
You could do this:
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);
}
}
And implement the GetArgs method like so (you still need a way of putting those values somewhere becuase the invocation never occurs):
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;
}
You infer the collection of name/value pairs from the expression tree created by the compiler, it's doable but kind of odd.

I think your API design is flawed if you need this, you would better have one method, which accepts a collection of some sort.
Code duplication like this is almost never the correct way to get things done.
EDIT
On topic:
I guess you can get the values from the stack: http://www.thescarms.com/dotnet/StackFrame.aspx

we do it like this:
var dict=new Dictionary
{
{"#param1",value1},
{"#param2",value2},
{"#param3",value3},
{"#param4",value4},
....
};
DALayer.ExecuteProc("procName",dict);
In the ExecuteProc function you can iterate over Dictionary object and set params using KeyValuePair object. But if you have to setup the datatype, lengths etc for the parameters then you have to do more work like preparing the sql command to query about parameters or passing more complicated object as parameter that contains information about datatype, length and direction etc.

Related

How do I refresh an array full of returned values of method calls?

In C#, I have a string array that I have written full full of "getter" method calls. They call methods in another class so that the array is populated with the needed strings. It looks something like this:
string[] mCalls = {c.get1(), c.get2(), c.get3()};
I'm sure this situation could apply to any program. However, in my program the variables these methods return are initially set with the string "Unchecked" - thus filling this example array with Unchecked 3 times. As my program goes on and things are checked, the values of the string variables get changed within the class they're in. I've been simply re-calling the getter methods at appropriate times to change what's in my array, like this:
mCalls[0] = c.get1();
mCalls[1] = c.get2();
mCalls[2] = c.get3();
I don't really like this. It seems inevitable that one day I'll have to change something, and if that happens I will have to manually do the tedious work of changing all of the indexing throughout my program. If this happens to be the best way I'm fine with that, but I assume there are better ways. So, in any case, is there a way to "refresh" the values in an array that is set up like this? And if so, what is it?
You want something like this:
public string[] MCalls
{
get
{
return new string[]{c.get1(), c.get2(), c.get3()};
}
private set;
}
and then use MCalls as if it is a regular variable whenever you want to access the arrays
You could change your array to contain functions instead of strings like this:
Func<string>[] mCalls = { c.get1, c.get2, c.get3...};
And then use it this way:
string c2 = mCalls[1]();
But note that this way every access is a method call. I'm not sure what you are really trying to achieve, there may be better overall designs than this approach.
Couple of options:
Create an array of lambdas:
var mCalls = new Func<object, string>[] {
(object o) => o.ToString() ,
(object o) => o.GetHashCode().ToString(),
(object o) => o.GetType().ToString(),
};
If the input to each lambda is the same you can create a lambda that returns an array:
Func<object, string[]> GetValues = (object o) => new string[]
{
o.ToString() ,
o.GetHashCode().ToString(),
o.GetType().ToString(),
};
Then just reload the array by calling the lambda:
mCalls = GetValues(c);
Note that it isn't technically refreshing the array, it's creating a new array. If you need to keep the array the same but just update the values you'd ned to loop through the array and assign the values by index.
What you could do is loop thorugh with reflection and get all methods from the class and from here you can get a list of method names. With this list you can assign to an array or run the methods by name or whatever. You can also filter the list to get your specific method names only:
var methodNames = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
To call the methods:
foreach(var method in methodNames)
{
typeof(MyClass).GetMethod(method).Invoke(t, new[] { "world" });
}

How to add multiple parameters to SQL command in one statement?

I have six lines of parameters like this:
cmd.Parameters.AddWithValue("#variable1", myvalue1);
cmd.Parameters.AddWithValue("#variable2", myvalue2);
cmd.Parameters.AddWithValue("#variable3", myvalue3);
and so on.
Is there any way to compress this a bit without directly inserting in the cmd.CommandText?
Edit: I guess I could have used a good old fashioned array. I've decided to stick with this though.
As far as I know, your code is the most compact possible in term of lines count, however you could use the List<SqlParameter> with the object initializer syntax to have just one line terminated by a semicolon to build your parameter list, then pass that list as the array of parameters expected by the AddRange method
List<SqlParameter> prm = new List<SqlParameter>()
{
new SqlParameter("#variable1", SqlDbType.Int) {Value = myValue1},
new SqlParameter("#variable2", SqlDbType.NVarChar) {Value = myValue2},
new SqlParameter("#variable3", SqlDbType.DateTime) {Value = myValue3},
};
cmd.Parameters.AddRange(prm.ToArray());
Notice that with this approach you need to define correctly the datatype of the parameter. In my example I have used some arbitrary types to show the correct syntax
A bit off-topic, by I think that in this general context is interesting to point out that AddWithValue is not to be considered when you want to get the best performance possible.
In this article on MSDN How data access code affects database perfomance is well explained why one should avoid the AddWithValue method for performance reasons.
In short, using AddWithValue could be a problem for the Sql Server Optimizer because the parameters of type string are passed with the size equal to the current length of the string. But this will force the Sql Server Optimizer to discard the query plan created for a previous identical call but with a string of different length.
It is better to call the SqlParameter constructor specifying the type and the size of the parameter and don't worry how to compress the size of the calls.
I took the question literally: "...in one statement" :)
Steve code is nice but it can be simplified a bit more using the most canonical SqlParameter constructor and implicit arrays declaration:
cmd.Parameters.AddRange(new []
{
new SqlParameter("#variable1", myValue1),
new SqlParameter("#variable2", myValue2),
new SqlParameter("#variable3", myValue3),
});
I think this will read very nicely as a one liner like this:
Usage:
// One liner to create and set SqlCommand parameters
cmd.SetParameters(Parameter("#variable1", myvalue1), Parameter("#variable2", myvalue2), Parameter("#variable3", myvalue3));
To support the one liner you need to create a function to wrap the Sql Parameter as a semantic bundle (Tuple like) as follows:
public SqlParameter Parameter(string name, object value)
{
return new SqlParameter(name, value);
}
Create a static class with an extension method to give us the syntactic sugar we are looking for. Notice the use of the params keyword which allows the multiple parameters in the above call to SetParameters.
public static class SqlDataUtils
{
public static void SetParameters(this SqlCommand command, params SqlParameter[] parameters)
{
command.Parameters.AddRange(parameters);
}
}
This answer is inspired by the accepted answer to Key value pairs in C# Params by Bryan Watts
Just for argument's sake, using the code example you gave where the stored proc variables are literally named variabe1, variable2, etc... you could do something like this:
string[] myValues = new string[] { "myvalue1", "myvalue2", "myvalue3", "myvalue4", "myvalue5", "myvalue6" };
for (int i = 0; i < 6; i++) { cmd.Parameters.AddWithValue("#variable" + (i + 1),myValues[i]); }
2 lines of ugly code... LOL
A loop like this may come in handy if you had say 25 - 50 values, though I don't see that very often. And you could use 2 arrays one for the variable names and one for the values, as long as the indexes match up, then this would work:
string[] myVarNames = new string[] { "variable1", "variable2", "variableThree", "variable4our", "variableFIVE", "variableSIX" };
string[] myValues = new string[] { "myvalue1", "myvalue2", "myvalue3", "myvalue4", "myvalue5", "myvalue6" };
for (int i = 0; i < 6; i++)
{
cmd.Parameters.AddWithValue("#" + myVarNames[i], myValues[i]);
}

Key Value array in C# put into parameter

Coming from PHP, I have never written C# before and I have encountered something like this in C#:
public string rule(string playerId, string action, params string[] optionalData){
...
}
and in PHP it is like this
public function rule($playerId, $action, $optionalData=array()){
...
}
In PHP I simply fill out the parameter for the $optionalData like this...
myVar->rule("123", "myAction", array('url'=>'review.com');
However in C# I am not sure how to fill the optionalData (params string[] optionalData) parameter as it is a key value parameter (like in the PHP example). My question is how do I create a key value array like the PHP that I created in my example and put into the parameter?
CoolClass cc = new CoolClass();
cc.rule("123", "myAction", ???);
I was searching google and was looking at dictionary and hashmaps etc but I am guessing it is an overkill or it does not work..
Many thanks!
When you were looking at dictionaries, you were definitely looking at the right facility.
If rule() in C# is in your own code, may I recommend changing the signature to:
public string rule(string playerId, string action, IDictionary<string, string> optionalData = new Dictionary<string, string>()){
...
}
What this allows you to do:
Operate on the values in optionalData the way that other C# programmers will expect.
The = new Dictionary<string, string>() part of the suggested method signature make the parameter truly optional. It will not be necessary when calling the method.
You can use IDictionary<T> methods to work with the data. Some syntax you should be somewhat familiar with (consider accessing by key optionalData["someString"].)
However, if rule() is not in your code, you would leave out the optionalData by simply omitting parameters. Examples of valid calls of the original C# method in your question:
rule("Bob", "load")
rule("Bob", "load", "url", "www.example.com") (In this case, optionalData[0].Equals("url", StringComparisonOptions.Ordinal) and optionalData[1].Equals("www.example.com", StringComparisonOptions.Ordinal) is true.
One thing to consider about the original method - keep in mind that rule("Bob", "load", 'url") is a valid call, and you would need to have a run-time check to make sure you had the right number of parameters. Another plus to using a Dictionary<TKey, TValue>. You may even consider writing an adapter method to the original rule(), if you can't change it.
You can use a Dictionary:
Dictionary<string,string[]>
or something like:
Dictionary<int, string[]>
I believe dictionary will work in your case.
You can use Dictionary <key_datatype, value_datatype> .
Example:
Your method definition here :
public string rule(string playerId, string action, Dictionary<string, string> optionalData){
...
}
Method call:
Dictionary<string, string> optionalData = new Dictionary<string, string>();
optionalData.Add("url", "review.com");
cc.rule("123", "myAction", optionalData);
Or
you can use DynamoObject to make it more easier to write:
dynamic optionalData = new ExpandoObject();
//The token after the dynamoObject period will be the key to the assigned value.
optionalData.url = "review.com";
cc.rule("123", "myAction", optionalData);
Your method can get the key-value pairs like this:
public string rule(string playerId, string action, dynamic optionalData)
{
...
foreach (var pair in (IDictionary<string, object>)optionalData)
{
if (group.Key == "url")
{
Console.WriteLine(group.Value);
}
else if (group.Key == "post")
{
Console.WriteLine(group.Value);
}
}
}

Evaluating a set of rules defined in a string

I made a system that creates a simple string with Function/Response format, example:
Check('Value'):ShowImage(#)|Check('Value'):OtherFunction(#)....and so on
Where Check is the name of a function, Value is the parameter, ShowImage is the name of a Response function, # is the entry paremeter (result of the previous function). The pipe splits another Function/Response pair that fires if the first Check('Value') function once "checked" were not satisfied (say, if the parameter was not accomplished the Check condition the function is invalid and hence the Response part in the first Function/Response pair is not executed, so system keep trying Functions awaiting to find the one that executes the right Response).
The way the application should work is to evaluate each rule (similar to a JavaScript eval function) and take appropriate action based on function results.
At first glance, it looks complicated, because first of all I need to cast the string to the right real C# function that will actually process the condition. Therefore, depending on the function result, decide where to point to execute my Response function.
Furthermore: This is just the kind example, because there are functions as * that represent something like: "any condition is true" what in almost all cases this function is the last in the chain (the default function).
That's my problem, I can't realize what is the easiest way to cope with this problem.
Maybe a chain of delegates? Lambdas? Anonymous stored into a structure...
Could you give me your measure/advise? Where to start?
Depending on the level of extensibility you want to have, I would say the most extensible way would be to use reflection to get method references, after you have parsed the input string.
You can start by splitting your problem into smaller subproblems.
Let's say you are aiming for something like this:
static void Main(string[] args)
{
string rules =
"Check(Morning):Say(Good morning)|" +
"Check(Afternoon):Say(Good afternoon)|" +
"Check(Evening):Say(Good night)";
// next, you need some **object instances** which will
// provide a context for your "test" and "action" methods.
// you don't want to use static methods if you
// went through the pain of defining such an architecture!
// let's say that a "Tester" object has a "Check" method,
// and an "Executor" object has a "Say" method:
var tester = new Tester("Afternoon");
var executor = new Executor();
// since I suck at regular expressions,
// I am using plain string methods to split
// the expression into tokens. You might want
// to add some validation
foreach (var rule in rules.Split('|'))
{
var result = Parse(rule, tester, executor);
if (result.TestPassed)
{
result.Execute();
break;
}
}
}
A "result" as it's used above would then have an interface like this:
public interface IResult
{
// returns true if a test is fulfilled
bool TestPassed { get; }
// executes the related action
void Execute();
}
And, if you want to delegate actual actions to some unknown methods, a reasonable way to implement it would be something like this:
public class Result : IResult
{
#region IResult Members
private readonly Func<bool> _testMethod;
public bool TestPassed
{
get { return _testMethod(); }
}
private readonly Action _actionMethod;
public void Execute()
{
_actionMethod();
}
#endregion
public Result(Func<bool> testMethod, Action actionMethod)
{
_testMethod = testMethod;
_actionMethod = actionMethod;
}
}
What's left is to use some reflection to get the actual methods out of your strings:
private static IResult Parse(string rule, object tester, object executor)
{
// split into test/action
var tokens = rule.Split(':');
// extract the method/parameter part for each expression
var test = GetMethodAndParams(tokens[0]);
var action = GetMethodAndParams(tokens[1]);
// use reflection to find actual methods
var testMethod = tester.GetType().GetMethod(test.Method);
var actionMethod = executor.GetType().GetMethod(action.Method);
// return delegates which will simply invoke these methods
return new Result
(
() => (bool)testMethod.Invoke(tester, new object[] { test.Param }),
() => actionMethod.Invoke(executor, new object[] { action.Param })
);
}
That is, more or less, your program's skeleton. You should be able to fill in the missing parts yourself, as an exercise. If you have problems, I can update the answer later.
A GetMethodAndParams method should split the input string into a Tuple (or your custom class) which contains the method name and its params as plain strings. Tester and Executor classes can also be implemented trivially.
It looks like you want a pattern along the lines of the .NET TryParse() methods. In that case, you would modify your check method to have an out parameter that is the value (represented in your example by #).
int result;
if(Check('Value', out result))
ShowImage(result);
else(Check('Value2', out result))
OtherFunction(result);
Finally I'm back here to post what I've done few weeks ago to solve this situation.
It was easy.
Regex class provide few options, one of those is "Explicit Catpure", all streams with the form (?) can be handled as strong typed parameters so, if the named group "IsNotEmptyorNull" then the function is present and it is promotable to casting using the form Enum.Parse("").
Snipet:
Regex rx = new Regex(#"(?<function>Check|BooleanOp)\('(?<param>[\w]+)'\){1}:(?<action>[\w]+){1}", RegexOptions.ExplicitCapture);
Match m;
Dictionary<FunctionArray, String> actions = new Dictionary<FunctionArray, String>();
if((m=rx.Match(strStream)).Success)
{
actions.Add((FunctionArray)Enum.Parse(typeof(FunctionArray), m.Groups["function"].value, true), m.Groups["param"].value);
}
Of course, there are lost the action part so I've improved the Dictionary stuff with an specialized Struct that can handle the functions and values as a source for decision taking.
Thanks to all. Ed.

Simple way to transpose data before passing to functions?

This is one of the hardest questions I've ever had to title here on SO. :) Although the title might not make sense, hopefully the question itself will.
Let's say I have a data structure like a Dictionary<string, List<double>>, and that I have functions that then take List<double>s as a parameter:
Dictionary<string, List<double>> candy_positions = new Dictionary<string, List<double>>();
candy_positions.Add( "Godiva", new List<double> { 1.0, 2.0, 4.0 });
EatCandy( candy_positions["Godiva"]);
...
But now I have decided that I don't want to do it this way. I want to replace my Dictionary with a List<CandyPositions>, where CandyPositions looks something like this:
public class CandyPositions
{
public double Sees;
public double Godiva;
public double Lindt;
}
However, I really would like to leave EatCandy() alone. Obviously, the problem is now that my data doesn't lend itself to be passed directly into the method. Instead, I have to do something lame like:
List<CandyPositions> candy_positions = new List<CandyPositions>();
...
var positions = from x in candy_positions select x.Godiva;
EatCandy( positions.ToList());
every time I want to call the method. I'd prefer to be able to do this in a more simple way, like:
EatCandy( candy_positions.GetPositionsFor( "Godiva"));
where the parameter "Godiva" matches the property name in the CandyPositions class.
After writing this question, I've realized that it isn't really about transposing data -- that part of it can be handled by writing an extension method. The part I don't know how to do is to pass in a property name, so that the extension method can take this and associate it with a class's property. I don't want to pass in a string, either, mainly because this will open the door for all sorts of runtime errors. I know how to make this work by passing "Godiva" to my extension method. What I really want to pass in is something akin to CandyPositions.Godiva instead.
This question is probably a little confusing, so in summary, I would accept the best of two types of answers:
Is there a better way to deal with transposing data, than to use an extension method + some way of accessing a property name?
Is there a way to specify the property that I want my extension method to retrieve, other than by a string?
My current extension method looks like this:
public static List<double> GetPositions( this List<CandyPositions> positions, string candy_name)
{
return (from x in positions select x.GetType().GetProperty(candy_name).GetValue(x, null)).Cast<double>().ToList();
}
Well, you could use:
public static List<double> GetPositions(this List<CandyPositions> positions,
Func<CandyPositions, double> projection)
{
return positions.Select(projection).ToList();
}
and call it with:
EatCandy(candyPositions.GetPositions(x => x.Godiva));
On the other hand, if you can change EatCandy to accept an IEnumerable<double> instead, you don't need the extra method - you can just use:
EatCandy(candyPositions.Select(x => x.Godiva));
without writing an extra method at all.
EDIT: If you need to iterate over two sequences at once, there are two options:
If you're using .NET 4, you can use the Zip extension method.
Otherwise, you can basically write your own:
using (var iterator1 = sequence1.GetEnumerator())
using (var iterator2 = sequence2.GetEnumerator())
{
while (iterator1.MoveNext() && iterator2.MoveNext())
{
var value1 = iterator1.Current;
var value2 = iterator2.Current;
// Use the values here
}
}

Categories