我想编写一个代码片段来执行以下操作,比如我有一个类让我们说MyClass:
class MyClass
{
public int Age { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
所以代码片段应该创建以下方法:
public bool DoUpdate(MyClass myClass)
{
bool isUpdated = false;
if (Age != myClass.Age)
{
isUpdated = true;
Age = myClass.Age;
}
if (Name != myClass.Name)
{
isUpdated = true;
Name = myClass.Name;
}
return isUpdated;
}
Run Code Online (Sandbox Code Playgroud)
所以我的想法是,如果我为任何类调用它应该创建DoUpdate
方法的片段,并且应该按照我在上面的例子中所做的那样编写所有属性.
所以我想知道:
改用实用方法怎么样:
public static class MyUtilities
{
public static bool DoUpdate<T>(
this T target, T source) where T: class
{
if(target == null) throw new ArgumentNullException("target");
if(source == null) throw new ArgumentNullException("source");
if(ReferenceEquals(target, source)) return false;
var props = typeof(T).GetProperties(
BindingFlags.Public | BindingFlags.Instance);
bool result = false;
foreach (var prop in props)
{
if (!prop.CanRead || !prop.CanWrite) continue;
if (prop.GetIndexParameters().Length != 0) continue;
object oldValue = prop.GetValue(target, null),
newValue = prop.GetValue(source, null);
if (!object.Equals(oldValue, newValue))
{
prop.SetValue(target, newValue, null);
result = true;
}
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
示例用法:
var a = new MyClass { Name = "abc", Age = 21 };
var b = new MyClass { Name = "abc", Age = 21 };
var c = new MyClass { Name = "def", Age = 21 };
Console.WriteLine(a.DoUpdate(b)); // false - the same
Console.WriteLine(a.DoUpdate(c)); // true - different
Console.WriteLine(a.Name); // "def" - updated
Console.WriteLine(a.Age);
Run Code Online (Sandbox Code Playgroud)
请注意,如果要在紧密循环(等)中使用它,则可以对其进行巨大优化,但这样做需要元编程知识。