简体   繁体   English

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

[英]Only allow certain classes to edit certain properties

I have a class with a PictureBox created as followed: 我有一个用PictureBox创建的类,如下所示:

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

I also have a class GameManager. 我也有一个GameManager类。 This is like a referee. 这就像裁判。

I want to make it so the BackColor of Tile.tilePB can only be edited by Gamemanager and nothing else, and no other class. 我想这样做,所以Tile.tilePB的BackColor只能由Gamemanager进行编辑,不能进行其他操作,而不能进行其他任何类的编辑。

I currently have a public PictureBox for Gamemanager (to edit) and a public get function for other classes, but I want to actually make this a valid system instead of what I have right now. 我目前有一个用于Gamemanager的公共PictureBox(用于编辑)和一个用于其他类的公共get函数,但实际上我想使其成为一个有效的系统,而不是现在拥有的系统。

Is this even possible? 这有可能吗? Please include explenation for the required code. 请附上必要代码的说明。

EDIT: I ran into an issue that I hadn't thought off: class Gamemanager is a static class. 编辑:我遇到了一个我没有想到的问题:类Gamemanager是一个静态类。 I do everything in that class via public static functions. 我通过公共静态函数来完成该类中的所有操作。 Is this still possible? 这还有可能吗? Since this doesn't work. 由于this不起作用。

Not sure if this is exactly what you are looking for, but I made this quick test and it seems to be able to differentiate the calling class: 不知道这是否正是您要查找的内容,但是我进行了此快速测试,它似乎能够区分调用类:

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());
        }
    }
}

You can't do this at compile time, but it can be done at runtime: 您不能在编译时执行此操作,但是可以在运行时完成:

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

Then somewhere: 然后在某个地方:

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

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

If you don't want to throw an exception or you want to do something different when "not authorized" class is trying to access the SetBackColor method then just replace throw new FieldAccessException() with return or whatever you want. 如果您不希望引发异常,或者当“未授权”类尝试访问SetBackColor方法时想要执行其他操作,则只需将return throw new FieldAccessException()替换为return或您想要的任何东西。

Bare in mind the approach presented here is inefficent and it just presents that in can be done at runtime and nothing more than that. 简而言之,这里介绍的方法效率不高,仅表明可以在运行时完成,仅此而已。

The only way I can think of where you enforce this at compile time, end up being a bit complicated. 我只能想到在编译时在哪里执行此操作的唯一方法,最终会变得有些复杂。 I don't think you'll want to do this. 我认为您不想这样做。

You can create an interface with properties/methods for everything that only the GameManager is allowed to do. 您可以为仅允许GameManager进行的所有操作创建具有属性/方法的界面。 You can implement this interface in a private inner class below Tile , and make sure the only way this object is created is by passing in a GameManager that receives it. 您可以在Tile下方的私有内部类中实现此接口,并确保创建此对象的唯一方法是传递一个接收该对象的GameManager。 Now, the only way the access can 'leak' is if the GameManager 'gives away' the object. 现在,访问权限“泄漏”的唯一方法是GameManager“放弃”该对象。

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

(seems) Simply not possible (似乎)根本不可能

After asking several programmers, the way I have coded everything and what I want seems to be simply impossible without immensely complicated code - to the point you are better off refacturing everything. 在问了几个程序员之后,如果没有极其复杂的代码,我编写一切代码的方式和我想要的东西似乎根本就不可能了,以至于您最好重新编写一切。 Since class Gamemanager is a static class, there will be no instances of it so you can not check if the 'object' that called it is of class Gamemanager. 由于Gamemanager类是静态类,因此不会有任何实例,因此您无法检查调用它的“对象”是否为Gamemanager类。 this also doesn't work since Gamemanager is, agian, static. this也不起作用,因为Gamemanager是静态的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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