Позволяет только определенным классам редактировать определенные свойства - PullRequest
0 голосов
/ 18 мая 2018

У меня есть класс с PictureBox, созданный следующим образом:

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

У меня также есть класс GameManager.Это похоже на рефери.

Я хочу сделать так, чтобы BackColor of Tile.tilePB мог редактировать только Gamemanager и ничего больше, и никакой другой класс.

В настоящее время у меня есть открытыйPictureBox для Gamemanager (для редактирования) и общедоступная функция get для других классов, но я на самом деле хочу сделать эту систему действительной, а не той, которая у меня есть сейчас.

Возможно ли это вообще?Пожалуйста, включите объяснение необходимого кода.

РЕДАКТИРОВАТЬ: Я столкнулся с проблемой, которую я не задумывался: класс Gamemanager является статическим классом.Я делаю все в этом классе через публичные статические функции.Это все еще возможно?Поскольку this не работает.

Ответы [ 4 ]

0 голосов
/ 18 мая 2018

(кажется) Просто невозможно

Спросив нескольких программистов, способ, которым я все кодировал и то, что я хочу, кажется просто невозможным без чрезвычайно сложного кода - до такой степени, что вам лучше реорганизовать все.Поскольку класс Gamemanager является статическим классом, его экземпляров не будет, поэтому вы не можете проверить, принадлежит ли вызывающий его «объект» к классу Gamemanager.this также не работает, так как Gamemanager, agian, статичен.

0 голосов
/ 18 мая 2018

Вы не можете сделать это во время компиляции, но это может быть сделано во время выполнения:

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 или что угодно.

Не обращайте внимания на подходпредставленный здесь неэффективен, и он просто представляет, что может быть сделано во время выполнения и не более того.

0 голосов
/ 18 мая 2018

Единственный способ, которым я могу думать о том, где вы применяете это во время компиляции, в конечном итоге оказывается немного сложным.Я не думаю, что вы захотите сделать это.

Вы можете создать интерфейс со свойствами / методами для всего, что разрешено делать только GameManager.Вы можете реализовать этот интерфейс в закрытом внутреннем классе ниже Tile и убедиться, что единственный способ создания этого объекта - передать GameManager, который его получает.Теперь единственный способ, которым доступ может «утечь», - это если 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; }         
        }
    }
}
0 голосов
/ 18 мая 2018

Не уверен, что это именно то, что вы ищете, но я сделал этот быстрый тест, и он, кажется, в состоянии дифференцировать вызывающий класс:

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());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...