仅允许某些类编辑某些属性

时间:2018-05-18 15:15:25

标签: c# class protection

我有一个创建了PictureBox的类,如下所示:

public class Tile
{
    public PictureBox tilePB = new PictureBox(); //properties don't matter in this case
}

我还有一个GameManager类。这就像一个裁判。

我想这样做,所以Tile.tilePB的BackColor只能由Gamemanager编辑,没有别的,也没有其他类。

我目前有Gamemanager的公共PictureBox(编辑)和其他类的公共get函数,但我想让它成为一个有效的系统,而不是我现在拥有的。

这甚至可能吗?请包含所需代码的explenation。

编辑:我遇到了一个我没想过的问题:类Gamemanager是一个静态类。我通过公共静态函数在该类中完成所有操作。这还有可能吗?由于this不起作用。

4 个答案:

答案 0 :(得分:0)

不确定这是否正是您正在寻找的,但我做了这个快速测试,它似乎能够区分调用类:

class Program
{
    static void Main(string[] args)
    {
        Type1 something1 = new Type1();
        Type2 something2 = new Type2();

        something1.runTest();
        something2.runTest();

        Console.ReadKey();
    }

    public class Type1
    {
        public void runTest()
        {
            Testing.edit(this);
        }
    }

    public class Type2
    {
        public void runTest()
        {
            Testing.edit(this);
        }
    }

    public static class Testing
    {
        public static void edit(object obj)
        {
            // This is where you test the calling class to make sure
            // it is allowed to edit.
            Console.WriteLine(obj.GetType().ToString());
        }
    }
}

答案 1 :(得分:0)

您无法在编译时执行此操作,但可以在运行时完成:

public class PictureBox
{
    private Color _backColor;

    public void SetBackColor(Color color)
    {
        //getting class type that called this method
        var stackTrace = new StackTrace();
        var stackFrames = stackTrace.GetFrames();

        var callingFrame = stackFrames[1];
        var method = callingFrame.GetMethod();

        //checking if the class type is GameManager
        if (!method.DeclaringType.IsAssignableFrom(typeof(GameManager)))
        {
            throw new FieldAccessException("Only GameManager can set the background color of a PictureBox!");
        }

        _backColor = color;
    }

    public Color BackColor => _backColor;
}

public class Tile
{
    public PictureBox tilePB { get; set; }
}

//example GameManager class
public class GameManager
{
    public void SetBackground()
    {
        var someTile = new Tile()
        {
            tilePB = new PictureBox()
        };

        var someColor = new Color();

        someTile.tilePB.SetBackColor(someColor);
    }
}

//example class that may want to set picturebox background color
public class MaliciousClass
{
    public void SetBackground()
    {
        var someTile = new Tile()
        {
            tilePB = new PictureBox()
        };

        var someColor = new Color();

        someTile.tilePB.SetBackColor(someColor);
    }
}

然后在某处:

var gm = new GameManager();
var mc = new MaliciousClass();

gm.SetBackground(); //this is fine
mc.SetBackground(); //this will throw an exception

如果您不想抛出异常,或者想要在“未授权”类尝试访问SetBackColor方法时执行其他操作,则只需将throw new FieldAccessException()替换为return或者你想要的任何东西。

请记住,这里介绍的方法是无效的,它只是表明可以在运行时完成,仅此而已。

答案 2 :(得分:0)

我能想到在编译时强制执行此操作的唯一方法,最终会有点复杂。我不认为你会这样做。

您可以为只允许GameManager执行操作的所有内容创建一个包含属性/方法的界面。您可以在Tile下面的私有内部类中实现此接口,并确保创建此对象的唯一方法是传入接收它的GameManager。现在,访问可以泄漏的唯一方式是“泄漏”。如果GameManager'放弃了#39;对象。

public class GameManager {
    public void AddTile(Tile t, Tile.IManagerHook m) {
        m.SomeProperty = "set from manager";
    }
}

public class Tile
{
    public object SomeProperty { get; private set; }

    public Tile(GameManager manager) {
        manager.AddTile(this, new ManagerHook(this));
    }

    public interface IManagerHook {
        object SomeProperty {get; set;}
    }


    private class ManagerHook : IManagerHook {
        private Tile _tile;
        public ManagerHook(Tile t) {
            _tile = t;
        }

        public object SomeProperty {
            get{ return  _tile.SomeProperty;}
            set { _tile.SomeProperty = value; }         
        }
    }
}

答案 3 :(得分:0)

(似乎)根本不可能

在询问了几位程序员之后,如果没有极其复杂的代码,我编写所有内容和我想要的内容的方式似乎根本不可能 - 到目前为止,你最好还是重构一切。由于类Gamemanager是一个静态类,因此不会有它的实例,因此您无法检查对象是否为'它叫做Gamemanager。由于Gamemanager是静态的,因此this也不起作用。