Reading method values ​​at runtime using reflection (+ hack)?

Short information:

We have a C # method that takes parameters.

inside this method, we need to add Sql parameters (according to method parameters).

It actually looks like this: http://i.stack.imgur.com/QP1y2.jpg (for enlargement) enter image description here

pay attention to

I can write a class that will have all the method arguments. But then I'll have to create a class container for each SP (and we have many).

Ok lets continue.

I thought to myself: " Why do I have to insert each parameter manually - if I already have: name

, type

, value

? Parameter method I do not want to do it, maybe thinking to do it for me" (let us now turn to the transformation of int <->DbType.Int32

)

But I ran into a problem. it is not the ability to read values ​​using reflection.

However I did manage to read the values ​​through reflection using a hack.

1) I made this example: (simulation for real scenario)

public static void MyMethod(int AddressId, string countryId, DateTime dt) //these are the arguments which need to be attached later
{

 MethodBase mi = MethodInfo.GetCurrentMethod();
 var hack = new {AddressId, countryId, dt}; //this is the HACK


var lstArguments = mi.GetParameters()  //get the parameter  name and types
                    .Select(p => new {
                                 name = p.Name  , type=p.GetType().Name
                                 }).ToList();


List < dynamic > lstParamValues= new List < dynamic > ();

foreach(PropertyInfo pi in hack.GetType().GetProperties())  //get the value(!!!) of each param 
{

       lstParamValues.Add(pi.GetValue(hack, null));
}


  dynamic dyn= myDBInstance; // get dynamic reference to the DB class instance ( 

for(int i = 0; i < lstArguments .Count; i++) //dynamically Invoke the method with param name+value.
{
    dyn.AddInParameter(lstArguments [i].name, ((lstParamValues[i] is int) ? DbType.Int32 : DbType.String), lstParamValues[i]);
}

}

      

And there is a DB class (to simulate AddInParameter

, to see if im will get values)

class myDB
{
    public void AddInParameter(string name, DbType dbt, object val)
    {
        Console.WriteLine("name=" + name + "    " + "DbType=" + dbt + "    " + "object val=" + val);
    }
}

      

And it works:

I followed the method with:

MyMethod(1, "2", DateTime.Now);

      

And the result was:

name=AddressId    DbType=Int32    object val=1
name=countryId    DbType=String    object val=2
name=dt    DbType=String    object val=05/02/2013 19:09:32

      

All perfectly.

C # question

How can I overcome this hack:

 var hack = new {AddressId, countryId, dt};  //  the method arguments names

      

In my example, I wrote it hardcoded.

The reflection method GetValue

only works because of this line.

Is there anything I can do to add, at runtime, the name of the method argument as a property, so I can do:

 foreach(PropertyInfo pi in SOMETHING.GetType().GetProperties()) 
   {
   }

      

Please consider this question as a C # question, not an ORM question.

Also, if you want to play with the running example code (just paste in the console proj): http://jsbin.com/azicut/1/edit

+3


source to share


3 answers


Does this provide any relief?

Do it once (in the DAL ctor):

SqlParameter sqlCmdFTSindexWordOnceParam = sqlCmdFTSindexWordOnce.Parameters.Add("@sID", SqlDbType.Int);
sqlCmdFTSindexWordOnceParam.Direction = ParameterDirection.Input;
SqlParameter sqlCmdFTSindexWordOnceParam2 = sqlCmdFTSindexWordOnce.Parameters.Add("@sIDpar", SqlDbType.Int);
sqlCmdFTSindexWordOnceParam2.Direction = ParameterDirection.Input;

      



Then in the call:

sqlCmdFTSindexWordOnceParam.Value = wdc.sID;
sqlCmdFTSindexWordOnceParam2.Value = wdc.sIDpar;                                    
sqlCmdFTSindexWordOnce.BeginExecuteNonQuery(callbackFTSindexWordOnce, sqlCmdFTSindexWordOnce);

      

Better performance than adding a parameter for each call.

0


source


AddWithValue

will at least keep you from typing the type name.

 command.Parameters.AddWithValue("@demographics", demoXml);

      



But you don't really go to that parameter either. A simple DTO class can make your code more readable. If I'm not mistaken, you're looking at something like pyhton locals

( Need something like locals in python ) which gives you function local variables as a key-value pair, and you can't do that in C # as far as I know.

or you just don't pass all the variables you can only pass Dictionary<string,object>

and add the key values ​​to the SqlParameter

0


source


I'm not familiar with how C # and .net works, but if it's java I would say:

save current parameters to arraylist or map

you can have 3 arraylists, one for each of the parameters that go into the call to the addInParameters method, or a map with all the values ​​included in it (the type parameter should have some duplication as it is now)

use a list of arrays as the only parameter in the insert / update methods use a for loop so that the AddInParameter call is written only once and the parameters are similar (array1 [0], array2 [0], array3 [0]), not actual values.

in php you can use associative arrays, does the .net network have associative arrays?

-3


source







All Articles