Reputation: 6190
I have several methods with a common pattern, i want to write a generic function that will take the column name as input and give the same result.
private void Query138()
{
var products = (from p in _context.Products
where p.Manufacturer == null
select p);
foreach (var productItem in products)
{
productItem.Manufacturer = string.Empty;
_context.UpdateProduct(productItem);
}
}
private void Query139()
{
var products = (from p in _context.Products
where p.ModelNumber == null
select p);
foreach (var productItem in products)
{
productItem.ModelNumber = string.Empty;
_context.UpdateProduct(productItem);
}
}
i want to write a generic function that will take the column name as input for the above methods.
Example:
private void Update(Expression<Fun<T,string>> pred = null)
{
//use the input column to select the data
//use the input column to set the new value and update
}
Upvotes: 2
Views: 732
Reputation: 394
This should works:
class SomeClass
{
public string prop1 { get; set; }
public string prop2 { get; set; }
}
///...
private void Update<T, TReturn>(Expression<Func<T, TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
var propName = body.Member.Name;
var prop = typeof(SomeClass).GetProperty(propName);
var products = (from p in contextProds
where prop.GetValue(p) == null
select p);
///...
}
Usage:
Update((SomeClass s) => s.prop1);
Update((SomeClass s) => s.prop2);
Where contextProds
is like List<SomeClass>
type.
Also you can visit this: Get name of property as a string.
Upvotes: 1
Reputation: 780
You can specify a getter and use it to generate a setter. This can be achieved as follows:
private void Update(Expression<Func<Product, string>> getExpr)
{
var value = Expression.Parameter(typeof(string), "value");
var setExpr = Expression.Lambda<Action<Product, string>>(
Expression.Assign(getExpr.Body, value), getExpr.Parameters[0], value);
Func<Product, string> getter = getExpr.Compile();
Action<Product, string> setter = setExpr.Compile();
var products = (from p in _context.Products
where getter(p) == null
select p);
foreach (var productItem in products)
{
setter(productItem, string.Empty);
_context.UpdateProduct(productItem);
}
}
And then called as follows:
Update( x => x.ModelNumber );
Upvotes: 0
Reputation: 952
You will need two expressions to achive this. One to get your value and the other to set it.
private void Update(Expression<Func<T, string>> getter, Expression<Action<T, string>> setter)
{
var products = (from p in _context.Products
where getter(p) == null
select p);
foreach (var productItem in products)
{
setter(productItem, string.Empty);
_context.UpdateProduct(productItem);
}
}
This way you can use i => i.[Your Attribute]
and (i, o) => i.[Your Attribute] = o
to call your function:
Update(i => i.[Your Attribute],(i, o) => i.[Your Attribute] = o);
Or in your case:
Update(i => i.Manufacturer,(i, o) => i.Manufacturer = o);
Update(i => i.ModelNumber,(i, o) => i.ModelNumber = o);
Upvotes: 1