使用对象属性作为字典中的键

发布于 2024-09-29 13:16:16 字数 712 浏览 3 评论 0原文

我想使用对象属性作为字典的键。这可以做到吗?

这样做的最终目标是使用它,以便可以在对象可能处于的各种状态下查看属性是否被锁定。这些锁定的值不会持久存在,仅存在于模型的业务规则中。

查看字段是否被锁定的理想代码如下所示;

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}
}

目的是避免键成为字符串,强类型键更可取。

I would like to use an objects property as the key for a dictionary. Can this be done?

The ultimate goal for this is to use this so can see if the property is locked or not, in various states that an object can be in. These locked value is not persisted, just exist in the business rules for the model.

Ideal code to see if field is locked would look like this;

bool ageLocked = myObject.IsFieldLocked( x => x.Age);

bool nameLocked = myObject.IsFieldLocked(x => x.Name);

IsFieldLocked being an extension method for the type of myObject.

I would like the dictionary to live in myObject and be replaceable with different dictionary variations based on the state of the object, for example, has placed an order or awaiting order would have different dictionary definitions.

Hopefully I would be able to use a factory to create the different dictionary variations;

Factory.CreateAwaitingOrderLockedFields()

Factory.CreateOrderPlacedLockedFields()

Defining the dictionary looking something like this

new Dictionary< ***MissingMagic***, bool>()
{
  { x => x.Age , true},
  { x => x.Name, false}
}

Aim is to avoid the key being a string, strongly typed key by far more desirable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

反目相谮 2024-10-06 13:16:16

我将字典简单地定义为 Dictionary

扩展方法可能如下所示:

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];
}

I'd define the dictionary simply as a Dictionary<string, bool>.

The extension method then could look something like this:

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];
}
天煞孤星 2024-10-06 13:16:16

这是我根据 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();
    }
}

Here is my cut down solution based on advice from 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;
        }
    }

With this I can do the following;

             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();
    }
}
被你宠の有点坏 2024-10-06 13:16:16

我认为你应该只使用继承。创建基类LockedField,然后创建继承该类的AwaitingOrderLockedField 和OrderPlacedLockedField。

class LockedField {
}

class AwaitingOrderLockedField : LockedField {
}

class OrderPlacedLockedField : LockedField {
}

您的字典将是 IDictionary

I think you should just use inheritance. Create a base class LockedField then create AwaitingOrderLockedField and OrderPlacedLockedField that inherit this class.

class LockedField {
}

class AwaitingOrderLockedField : LockedField {
}

class OrderPlacedLockedField : LockedField {
}

You dictionary will be IDictionary<LockedField, bool>

萌面超妹 2024-10-06 13:16:16

您需要在要用作字典中键的类中实现 IComparable 接口:

public class MyObject : IComparable {
  public int CompareTo(MyObject obj) {
    // Comparison Logic
  }
}

由于这实际上并不是对象成员的选项,因此您可以使用 DictionaryDictionaryDictionary以字段名称作为键,并在 IsFieldLocked() 方法中进行一些反射,以从强类型字段中删除字符串。

You will need to implement the IComparable interface in the class you want to use as key in a dictionary:

public class MyObject : IComparable {
  public int CompareTo(MyObject obj) {
    // Comparison Logic
  }
}

Since this is not really an option for a member of an object you may was well use Dictionary<string, bool> with the field name as the key and a bit of reflection in your IsFieldLocked() method to strip out the string from the strongly typed field.

旧瑾黎汐 2024-10-06 13:16:16

您可以将任何类型声明为键的字典;

Dictionary<Form,bool>

将创建一个字典,其中表单元素用作键。

这是你问的吗?

如果要使用多个不同的对象作为键,您可以使用 Dictionary 或让所有对象继承另一个对象 Dictionary

You can declare the dictionary with any type as key;

Dictionary<Form,bool>

would create a dictionary where form elements are used as key.

Is this What you where asking?

If several different objects are to be used as key you could use Dictionary<object,bool>or let all objects inherit from another object Dictionary<masterobject,bool>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文