简体   繁体   中英

Protect the Controls collection of my own control from users in C#

Good day. I create my control that contains group of another UserControls, for example:

public class MySuperControl : Control
{
    private List<MySmallControl> _smallControls;

    public MySuperControl()
    {
        //_smallControls = ... //creating of small controls
        this.Controls.AddRange(_smallControls);
    }

    class MySmallControl : UserControl
    {
        //contains button and checkbox
    }
}

在此处输入图片说明

It is all right, but the users of MySuperControl have access to Controls property and can change Location of small controls and even remove their from collection! Encapsulation is broken! Example of user's bad actions:

MySuperControl c=new MySuperControl();
c.Controls.Clear();

or

MySuperControl c=new MySuperControl();
foreach (Control smallControl in c.Controls)
{
    smallControl.Location = new Point(999, 999);
}

This will result to crash MySuperControl:

在此处输入图片说明

How to protect inner controls of MySuperControl? Thanks.

public class MyUserControl : UserControl
{
    public new Control.ControlCollection Controls
    {
        get { throw new NotSupportedException(); }
    }
}

This is the best you can get from this situation. You can access the controls collection by calling base.Controls. If someone is smart enough, however to cast your MyUserControl to UserControl he will be able to modify the collection but there is nothing you can do about that.

I came up with this solution:

public class MySuperControl : Control
{
    private List<MySmallControl> _smallControls;

    public MySuperControl()
    {
        Controls = new CControlCollection(this);
        //_smallControls = ... //creating of small controls
        ((Control)this).Controls.AddRange(_smallControls);
    }

    class MySmallControl : UserControl
    {
        //contains button and checkbox
    }

    //Wrapper for the Control.Controls property of the MySuperControl
    public new CControlCollection Controls { get; private set; }

    public class CControlCollection : ICollection<Control>
    {
        private Collection<Control> items;
        private MySuperControl parent;

        public CControlCollection(MySuperControl parent)
        {
            items = new Collection<Control>();
            this.parent = parent;
        }

        public int Count
        {
            get { return items.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public void Add(Control item)
        {
            items.Add(item);
            ((Control)parent).Controls.Add(item);
        }

        public void AddRange(Control[] itemsArray)
        {
            foreach (Control item in itemsArray)
            {
                items.Add(item);
                ((Control)parent).Controls.Add(item);
            }
        }

        public void Clear()
        {
            foreach (Control c in items)
            {
                ((Control)parent).Controls.Remove(c);
            }
            items.Clear();
        }

        public bool Contains(Control item)
        {
            return items.Contains(item);
        }

        public void CopyTo(Control[] array, int arrayIndex)
        {
            items.CopyTo(array, arrayIndex);
        }

        public bool Remove(Control item)
        {
            ((Control)parent).Controls.Remove(item);
            return items.Remove(item);
        }

        public IEnumerator<Control> GetEnumerator()
        {
            return items.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return items.GetEnumerator();
        }
    }
}

Users can still access to Control.Controls property by cast MyUserControl to Control:

MySuperControl c=new MySuperControl();
((Control)c).Controls.Clear();

But if they use c.Controls instead, all will work normally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM