这是我根据herzmeister der welten的建议简化后的解决方案
public class MyDtoOne : BaseFieldLockingDto<MyDtoOne>
{
public string Name { get; set; }
public int Age { get; set; }
public MyDtoOne()
{
LockedFields = new LockedFields<MyDtoOne>
{
{ x => x.Age, false },
{ x => x.Name, true }
};
}
}
public class MyDtoTwo : BaseFieldLockingDto<MyDtoTwo>
{
public DateTime DateOfBirth { get; set; }
public MyDtoTwo()
{
LockedFields = new LockedFields<MyDtoTwo>
{
{x => x.DateOfBirth, false}
};
}
}
public class BaseFieldLockingDto<TBaseObject>
{
public LockedFields<TBaseObject> LockedFields { get; set; }
public bool IsFieldLocked<TField>(Expression<Func<TBaseObject, TField>> propertyExpression)
{
return LockedFields.IsFieldLocked(propertyExpression);
}
}
public class LockedFields<TBaseObject> : Dictionary<string, bool>
{
public void Add<TField>(Expression<Func<TBaseObject, TField>> propertyExpression, bool isLocked)
{
Add(GenerateKey(propertyExpression), isLocked);
}
private static string GenerateKey<TField>(Expression<Func<TBaseObject, TField>> propertyExpression)
{
return GetLambdaPropertyName(propertyExpression);
}
public bool IsFieldLocked<TField>(Expression<Func<TBaseObject, TField>> propertyExpression)
{
if (Count == 0)
return false;
string propertyName = GetLambdaPropertyName(propertyExpression);
if (ContainsKey(propertyName) == false)
return false;
return this[propertyName];
}
private static string GetLambdaPropertyName<TField>(Expression<Func<TBaseObject, TField>> propertyExpression)
{
var lambda = (LambdaExpression) propertyExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression) lambda.Body;
memberExpression = (MemberExpression) unaryExpression.Operand;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
if (memberExpression == null)
{
throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.",
propertyExpression));
}
return memberExpression.Member.Name;
}
}
通过这个我可以做到以下的事情:
private static void Main(string[] args)
{
var myDtoOne = new MyDtoOne();
bool ageLocked = myDtoOne.IsFieldLocked(x => x.Age);
bool nameLocked = myDtoOne.IsFieldLocked(x => x.Name);
Console.WriteLine(string.Format("Age locked is {0}", ageLocked ? "true" : "false"));
Console.WriteLine(string.Format("Name locked is {0}", nameLocked ? "true" : "false"));
myDtoOne.LockedFields = new LockedFields<MyDtoOne> {{x => x.Age, true}, {x => x.Name, false}};
bool ageLocked1 = myDtoOne.IsFieldLocked(x => x.Age);
bool nameLocked1 = myDtoOne.IsFieldLocked(x => x.Name);
Console.WriteLine(string.Format("Age locked is {0}", ageLocked1 ? "true" : "false"));
Console.WriteLine(string.Format("Name locked is {0}", nameLocked1 ? "true" : "false"));
var myDtoTwo = new MyDtoTwo();
bool dateOfBirth = myDtoTwo.IsFieldLocked(x => x.DateOfBirth);
Console.WriteLine(string.Format("Date of birth locked is {0}", dateOfBirth ? "true" : "false"));
myDtoTwo.LockedFields = new LockedFields<MyDtoTwo>() {{x => x.DateOfBirth, true}};
bool dateOfBirth1 = myDtoTwo.IsFieldLocked(x => x.DateOfBirth);
Console.WriteLine(string.Format("Date of birth locked is {0}", dateOfBirth1 ? "true" : "false"));
Console.ReadLine();
}
}