I have a class with two DateTime fields, I want to have one shared method to set both of them. Would it be possible somehow to do so with Func Delegate?
private void SetDateTimeField(MyClass class, Func<SupportTicket, DateTime> selector, DateTime date)
{
//using selector to select a field of the class and set date parameter to it
}
and then use it like:
SetDateTimeField(class, c => c.DateTimeField1, DateTime.UtcNow);
SetDateTimeField(class, c => c.DateTimeField2, DateTime.UtcNow);
This question less about practicality of it, but rather understanding how to do it. Is it possible?
CodePudding user response:
If DateTime fields are actually fields (not properties), you can use ref
.
var c = new MyClass();
MyClass.SetDateTimeField(c, c => ref c.dt1, DateTime.Now);
MyClass.SetDateTimeField(c, c => ref c.dt2, DateTime.Now);
public class MyClass {
public DateTime dt1;
public DateTime dt2;
public delegate ref DateTime Selector(MyClass c);
public static void SetDateTimeField(MyClass c, Selector sel, DateTime dt) {
sel(c) = dt;
}
}
CodePudding user response:
Instead of passing a function, pass a function expression. You can then derive the property from the expression and set its value.
public class SupportTicket
{
public DateTime DT1 { get; set; }
public DateTime DT2 { get; set; }
}
private static void SetDateTimeField<TObj, TProp>(TObj obj, Expression<Func<TObj, TProp>> selectorExpr, TProp date)
{
// Get the body of the function as a member access expression
MemberExpression memberExpr = selectorExpr.Body as MemberExpression;
if (memberExpr != null)
{
// Get the property from the member access expression and set the value
MemberInfo memberInfo = memberExpr.Member;
PropertyInfo propertyInfo = memberInfo.DeclaringType.GetProperty(memberInfo.Name);
propertyInfo.SetValue(obj, date);
}
else
{
throw new Exception("You must use a member access expression");
}
}
Sample usage:
SupportTicket ticket = new SupportTicket();
DateTime dt = DateTime.Now;
SetDateTimeField(ticket, e => e.DT1, dt);
SetDateTimeField(ticket, e => e.DT2, dt);
Console.WriteLine(ticket.DT1);
Console.WriteLine(ticket.DT2);
Console.ReadLine();
CodePudding user response:
If you want to change a property based on name you can do it like this:
private void SetDateTimeField(MyClass classX, String selector, DateTime dateX)
{
//using selector to select a field of the class and set date parameter to it
var prop = typeof(MyClass).GetProperty(selector);
prop.SetValue(classX, dateX);
}
SetDateTimeField(class, "DateTimeField1", DateTime.UtcNow);
SetDateTimeField(class, "DateTimeField2", DateTime.UtcNow);