1

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

public interface IEngine { 
    void Foo(); 
} 

public interface IWheels { 
    void Foo(); 
} 

public interface IChassie { 
    void Foo(); 
} 

public interface IPaintShop { 
    void PaintWheels(IWheels wheels); 
    void PaintChassie(IChassie chassie); 
    void ChromeEngine(IEngine engine); 
} 

var paintShop = Impromptu.ActLike<IPaintShop>(); 
var car = Impromptu.ActLike(new [] {typeof(IEngine), typeof(IWheels), typeof(IChassie) }); 
// dynamic car = Impromptu.ActLike(new [] {typeof(IEngine), typeof(IWheels), typeof(IChassie) }); // Same error 
paintShop.PaintWheels(car); // RuntimeException as car is dynamic and not the expected IWheels 

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Лучший перегружен матч метод 'MyStuff.PaintWheels (IWheels)' имеет некоторые недопустимые аргументы

Я пытался бросить но получить InvalidCastException:

paintShop.PaintWheels((IWheels)car); 

System.InvalidCastException: невозможно выполнить объект типа 'ImpromptuInterface.ActLikeCaster' для ввода 'MyStuff.IWheels'.

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

var wheels = Impromptu.CoerceConvert(car, typeof (IWheels)); 
paintShop.PaintWheels(wheels); 

Что такое правильный способ достижения выполнения множественного наследования с помощью импровизированного-интерфейс?

+0

Что делает 'ICar' определение интерфейса выглядит? – AGB

+0

@AGB Я добавил его сейчас. В этом примере не так много. –

+0

Вы имеете в виду, что 'IEngine',' IWheels' и 'IChassie' не связаны? Вы упомянули, что они должны быть унаследованы в вашем посте, но, как написано, они не наследуют друг от друга вообще. – AGB

ответ

1

Проблемы, с которыми вы сталкиваетесь, связаны с безопасностью типа - даже при использовании библиотеки, такой как Impromptu, вы должны быть уверены, что компилятор и среда выполнения уверены, что объект, который вы передаете в метод, является типом, который метод требует.

ActLike<T> может реализовывать множество интерфейсов, но он возвращает только один типизированный экземпляр T, поэтому без типа, сообщающего компилятору, что ваш экземпляр реализует несколько интерфейсов, вы будете вынуждены отбрасывать необходимые интерфейсы.

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

Попробуйте что-то вроде следующего:

using System; 
using ImpromptuInterface; 
using ImpromptuInterface.Dynamic; 

namespace Example 
{ 
    public interface IEngine 
    { 
     void Foo(); 
    } 

    public interface IWheels 
    { 
     void Foo(); 
    } 

    public interface IChassie 
    { 
     void Foo(); 
    } 

    public interface IPaintShop 
    { 
     void PaintWheels(IWheels wheels); 
     void PaintChassie(IChassie chassie); 
     void ChromeEngine(IEngine engine); 
    } 

    internal class Program 
    { 
     public static void Main(string[] args) 
     { 
      var ps = new 
      { 
       PaintWheels = ReturnVoid.Arguments<IWheels>(wheels => wheels.Foo()), 
       PaintChassie = ReturnVoid.Arguments<IChassie>(chassie => chassie.Foo()), 
       ChromeEngine = ReturnVoid.Arguments<IEngine>(engine => engine.Foo()) 
      }; 
      var paintShop = ps.ActLike<IPaintShop>(); 

      var fullCar = new 
      { 
       Foo = ReturnVoid.Arguments(() => Console.WriteLine("Hello World!")) 
      }; 

      var car = fullCar.ActLike<IEngine>(typeof(IChassie),typeof(IWheels)); 

      //each of these 3 calls prints "Hello World!" to the console 
      paintShop.PaintWheels((IWheels)car);//need to tell the compiler to cast your car to type IWheels because var car is of type IEngine 
      paintShop.PaintChassie(car as IChassie);//need to tell the compiler to cast your car to type IChassie because var car is of type IEngine 
      paintShop.ChromeEngine(car);//works sans cast because var car is of type IEngine 

      //each of these 3 calls prints "Hello World!" to the console, too 
      dynamic dynamicCar = car; 
      paintShop.PaintWheels(dynamicCar);//by using dynamic you disable the compile time 
      paintShop.PaintChassie(dynamicCar);//type checking and the compiler "trusts you" on the typing 
      paintShop.ChromeEngine(dynamicCar);//since Impromptu wrapped your object and implemented the interfaces for you, there is no runtime exception 

      Console.ReadLine(); 
     } 
    } 
} 
+0

Спасибо, но 'public interface ICar: IChassie, IWheels, IEngine' как в вашем коде будет означать множественное наследование компиляции, а не время выполнения. –

+0

Хорошо. Я буду обновлять свой ответ без 'ICar' – AGB

+0

Обновлен мой ответ на удаление' public interface ICar: IChassie, IWheels, IEngine {} ' – AGB

Смежные вопросы