I have a table called "Account." Account has 3 columns: id, acct_name, is_privileged.
When I write something like "account.", visual studio provides me with a list of attributes/methods I can use. Hence, I get the option of using account.id
, account.acct_name
, and account.is_privileged
.
However, I would like to change a particular column's value dynamically, without typing in my column's name. I am getting the column's name dynamically as a string variable. Is it possible to achieve it? If so, how?
My code is as follows:
set_col_name = rowRule.Cells["setcolumnnameDataGridViewTextBoxColumn"].Value.ToString();
set_col_value = rowRule.Cells["setcolumnvalueDataGridViewTextBoxColumn"].Value.ToString();
foreach (DataGridViewRow rowAcc in dgvAccount.Rows)
{
if (isComparable(rowAcc.Cells[col_name].Value.ToString(), comp_operator, col_value))
{
account.id = (int)rowAcc.Cells["idDataGridViewTextBoxColumn2"].Value;
using (ae = new AccountEntities())
{
var temp = ae.Accounts.SingleOrDefault(a => a.id == account.id);
temp.is_privileged = set_col_value; //learn how to do this dynamically
ae.SaveChanges();
}
}
}
Where I do temp.is_privileged, I'd like to achieve something like, temp."set_col_name" = set_col_value;
Instead of specifying the column name directly as being "is_privileged" in this case, I'd like to pass a string to specify it.
Thank you.
If I understand your problem statement correctly, you want something like this to work:
Account temp = // with temp coming from a library such as EntityFramework
temp.SetValue(set_col_name, set_col_value);
this is quite easy to achieve with either pure reflection or Linq Expression Trees (which I opted for):
static class Ext
{
public static void Set<T, TProperty>(this T instance, string propertyName, TProperty value)
{
var instanceExpression = Expression.Parameter(typeof(T), "p");
var propertyGetterExpression = Expression.PropertyOrField(instanceExpression, propertyName);
//generate setter
var newValueExpression = Expression.Parameter(typeof(TProperty), "value");
var assignmentExpression = Expression.Assign(propertyGetterExpression, newValueExpression);
var lambdaExpression = Expression.Lambda<Action<T, TProperty>>(assignmentExpression, instanceExpression, newValueExpression);
var setter = lambdaExpression.Compile();// the generated lambda will look like so: (p, value) => p.{your_property_name} = value;
setter(instance, value);
}
}
one advantage of this method over pure reflection is that you can build the setter delegate once and call it multiple times at later stage (I will leave this with you to experiment)
with the above in place, hopefully you should be able to do something like this:
var set_col_name = "is_privileged";
var set_col_value = true;
using (ae = new AccountEntities())
{
var temp = ae.Accounts.SingleOrDefault(a => a.id == account.id);
temp.Set(set_col_name, set_col_value);
temp.Set("acct_name", "test");
ae.SaveChanges();
}
You need some reflection in this one. For example
public static void CopyValues<T>(T obj1, T obj2)
{
var type = typeof(T);
foreach (var prop in type.GetProperties())
{
prop.SetValue(obj1, prop.GetValue(obj2));
}
}
And use the above function like this:
var source = new Accounts(){is_privileged = false};
var destiny = new Accounts();
CopyValues(source, destiny);
It depends of what you are loking for, but the key is to use REFLECTION!