Отключить приведение к явному типу времени выполнения - PullRequest
0 голосов
/ 27 апреля 2020

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

Мотивация для этого в конце.

Мой пример с более подробными объяснениями:

class Program
{
    private interface Interface1
    {
        public void InterfaceAction();
    }

    private class Class1 : Interface1
    {
        public void InterfaceAction()
        {
            Console.WriteLine("Interface action");
        }

        public void ClassAction()
        {
            Console.WriteLine("Class action");
        }
    }

    private class Class2
    {
        public void UseTheInterface(Interface1 interfaceObject)
        {
            // At the context of Class2 execution, from the signature of the method I only know that 
            //      received object is of Interface1, thus I can only use its method "InterfaceAction"
            interfaceObject.InterfaceAction();

            // As the runtime type of "interfaceObject" is Class1, I can cast to it
            Class1 casted = (Class1) interfaceObject;

            // Now after I revealed the object real type, I can use its unique method "ClassAction"
            casted.ClassAction();
        }
    }

    static void Main(string[] args)
    {
        Class1 obj1 = new Class1();
        Class2 obj2 = new Class2();

        // Here an auto cast to Interface1 is made on obj1
        obj2.UseTheInterface(obj1);

        // Actual output:
        //      Interface action
        //      Class action

        // Wanted output:
        //      Interface action
        //      Cast exception at line 35
    }
}

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

Допустим, я хочу передать объект в некоторый класс и раскрыть только часть его методов с помощью интерфейса, как показано выше. Я не хочу полагаться на то, что другой класс будет использовать его должным образом и использовать только методы интерфейса, я хочу убедиться, что он не может получить доступ ни к каким другим методам, кроме методов в интерфейсе.

Предполагая, что другой класс принимает интерфейс в качестве параметра для функции, он знает только свой объявленный тип и, следовательно, не должен пытаться привести его. Тем не менее, другой класс может просто попытаться использовать метод «грубой силы» для каждого из разработчиков «Interface1», пока не найдет соответствующий тип. Также можно было бы получить тип среды выполнения с помощью метода расширения .GetType (), а затем выполнить приведение с использованием условия переключения без грубой форсировки.

Спасибо за помощь.

1 Ответ

0 голосов
/ 27 апреля 2020

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

Пример

class Program
{
    private interface Interface1
    {
        void InterfaceAction();
    }

    private class Class1ToInterface1 : Interface1
    {
        Class1 wrapped;
        public Class1ToInterface1(Class1 wrapped)
        {
            this.wrapped = wrapped;
        }

        public void InterfaceAction()
        {
            wrapped.InterfaceAction();
        }
    }

    private class Class1 : Interface1
    {
        public void InterfaceAction()
        {
            Console.WriteLine("Interface action");
        }

        public void ClassAction()
        {
            Console.WriteLine("Class action");
        }
    }

    private class Class2
    {
        public void UseTheInterface(Interface1 interfaceObject)
        {
            // At the context of Class2 execution, from the signature of the method I only know that 
            //      received object is of Interface1, thus I can only use its method "InterfaceAction"
            interfaceObject.InterfaceAction();

            // As the runtime type of "interfaceObject" is Class1, I can cast to it
            Class1 casted = (Class1)interfaceObject; // InvalidCastException

            // Now after I revealed the object real type, I can use its unique method "ClassAction"
            casted.ClassAction(); // Won't get this far
        }
    }

    static void Main(string[] args)
    {
        Class1 obj1 = new Class1();
        Class2 obj2 = new Class2();
        Interface1 interfaceToObj1 = new Class1ToInterface1(obj1);

        // Here an auto cast to Interface1 is made on obj1
        obj2.UseTheInterface(interfaceToObj1);

        // Actual output:
        //      Interface action
        //      Class action

        // Wanted output:
        //      Interface action
        //      Cast exception at line 35
    }
}

Это должно сгенерировать System.InvalidCastException "Невозможно привести объект типа 'Class1ToInterface1' к типу 'Class1' «. на линии:

Class1 casted = (Class1)interfaceObject; // InvalidCastException
...