.net 对字典中的键使用对象属性
我想使用objects属性作为字典的键。这能做到吗 这样做的最终目的是使用它,以便在对象可能处于的各种状态下查看属性是否被锁定。这些锁定的值不会持久化,只是存在于模型的业务规则中 查看字段是否锁定的理想代码如下所示.net 对字典中的键使用对象属性,.net,dictionary,lambda,.net,Dictionary,Lambda,我想使用objects属性作为字典的键。这能做到吗 这样做的最终目的是使用它,以便在对象可能处于的各种状态下查看属性是否被锁定。这些锁定的值不会持久化,只是存在于模型的业务规则中 查看字段是否锁定的理想代码如下所示 bool ageLocked = myObject.IsFieldLocked( x => x.Age); bool nameLocked = myObject.IsFieldLocked(x => x.Name); IsFieldLocked是myObject类型的
bool ageLocked = myObject.IsFieldLocked( x => x.Age);
bool nameLocked = myObject.IsFieldLocked(x => x.Name);
IsFieldLocked是myObject类型的扩展方法
我希望字典位于myObject中,并根据对象的状态使用不同的字典变体进行替换,例如,已下订单或等待订单将具有不同的字典定义
希望我能够使用工厂来创建不同的字典变体
Factory.CreateAwaitingOrderLockedFields()
Factory.CreateOrderPlacedLockedFields()
定义字典看起来像这样
new Dictionary< ***MissingMagic***, bool>()
{
{ x => x.Age , true},
{ x => x.Name, false}
}
新词典<***MissingMagic***,bool>()
{
{x=>x.Age,true},
{x=>x.Name,false}
}
这样做的目的是为了避免键是字符串,强类型键,这样做更可取。我认为您应该使用继承。创建基类LockedField,然后创建继承此类的AwaitingOrderLockedField和OrderPlacedLockedField
class LockedField {
}
class AwaitingOrderLockedField : LockedField {
}
class OrderPlacedLockedField : LockedField {
}
您的词典将是
i词典
您可以将任何类型的词典声明为键
Dictionary<Form,bool>
字典
将创建一个字典,其中表单元素用作键
这就是你要问的吗
如果要使用多个不同的对象作为键,则可以使用
字典
,或者让所有对象从另一个对象继承字典
,我将字典定义为字典
扩展方法可以如下所示:
public static bool IsFieldLocked<TField>(this MyClass self, Expression<Func<MyClass, TField>> propertyExpression)
{
// note: null checks etc omitted for brevity
var lambda = (LambdaExpression)propertyExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
{
memberExpression = (MemberExpression)lambda.Body;
}
string propertyName = memberExpression.Member.Name;
return self.InternalLockedFieldsDictionary[propertyName];
}
公共静态bool是字段锁定的(此MyClass自身,表达式propertyExpression)
{
//注:为简洁起见,省略了空检查等
var lambda=(LambdaExpression)propertyExpression;
成员表达成员表达;
if(lambda.Body是一元表达式)
{
var unaryExpression=(unaryExpression)lambda.Body;
memberExpression=(memberExpression)unaryExpression.Operator;
}
其他的
{
memberExpression=(memberExpression)lambda.Body;
}
字符串propertyName=memberExpression.Member.Name;
返回self.InternalLockedFieldsDictionary[propertyName];
}
您需要在要用作字典键的类中实现IComparable接口:
public class MyObject : IComparable {
public int CompareTo(MyObject obj) {
// Comparison Logic
}
}
由于这实际上不是对象成员的选项,因此您可以使用
字典
,将字段名作为键,并在isfieldlock()
方法中进行一些反射,以从强类型字段中删除字符串。以下是基于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;
}
}
公共类MyDtoOne:BaseFieldLockingDto
{
公共字符串名称{get;set;}
公共整数{get;set;}
公共MyDtoOne()
{
LockedFields=新的LockedFields
{
{x=>x.Age,false},
{x=>x.Name,true}
};
}
}
公共类MyDtoTwo:基线锁定DTO
{
公共日期时间出生日期{get;set;}
公共MyDtoTwo()
{
LockedFields=新的LockedFields
{
{x=>x.DateOfBirth,false}
};
}
}
公共类基线锁定DTO
{
公共锁定字段锁定字段{get;set;}
公共bool是字段锁定的(表达式属性Expression)
{
返回LockedFields.IsFieldLocked(propertyExpression);
}
}
公共类锁定字段:字典
{
public void Add(表达式属性Expression,bool已锁定)
{
添加(GenerateKey(propertyExpression),已锁定);
}
私有静态字符串GenerateKey(表达式属性Expression)
{
返回GetLambdPropertyName(propertyExpression);
}
公共bool是字段锁定的(表达式属性Expression)
{
如果(计数=0)
返回false;
字符串propertyName=GetLambdaPropertyName(propertyExpression);
if(ContainsKey(propertyName)==false)
返回false;
返回此[propertyName];
}
私有静态字符串GetLambdaPropertyName(表达式propertyExpression)
{
var lambda=(LambdaExpression)propertyExpression;
成员表达成员表达;
if(lambda.Body是一元表达式)
{
var unaryExpression=(unaryExpression)lambda.Body;
memberExpression=(memberExpression)一元表达式。操作数;
}
其他的
{
memberExpression=lambda.Body作为memberExpression;
}
if(memberExpression==null)
{
抛出新ArgumentException(string.Format)(“表达式{0}引用的是方法,而不是属性。”,
属性表达式);
}
返回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();
}
}
private static void Main(字符串[]args)
{
var myDtoOne=新的myDtoOne();
bool ageLocked=myDtoOne.IsFieldLocked(x=>x.Age);
bool nameLocked=myDtoOne.IsFieldLocked(x=>x.Name);
WriteLine(string.Format(“Age locked是{0}”,Age locked是?“true”:“false”);
WriteLine(string.Format(“Name locked is{0}”,nameLocked?“true”):“false”);
myDtoOne.LockedFields=新的LockedFields{{x=>x.Age,true},{x=