简体   繁体   English

带有即兴界面的运行时多重继承

[英]Runtime multiple inheritance with impromptu-interface

I'm trying to get runtime multiple inheritance to work using impromptu-interface but I'm stuck when I want to pass the object along to a method.我正在尝试使用即兴接口让运行时多重继承工作,但是当我想将对象传递给方法时我被卡住了。

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 : The best overloaded method match for 'MyStuff.PaintWheels(IWheels)' has some invalid arguments Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“MyStuff.PaintWheels(IWheels)”的最佳重载方法匹配有一些无效参数

I've tried to cast but get InvalidCastException :我试图投射但得到InvalidCastException

paintShop.PaintWheels((IWheels)car);

System.InvalidCastException : Unable to cast object of type 'ImpromptuInterface.ActLikeCaster' to type 'MyStuff.IWheels'. System.InvalidCastException:无法将“ImpromptuInterface.ActLikeCaster”类型的对象转换为“MyStuff.IWheels”类型。

The following works but I'm not sure this is the correct way;以下工作,但我不确定这是正确的方法; it seem unwarranted to convert car to IWheels when IWheels interface should already be inherited:IWheels接口应该已经被继承时,将汽车转换为IWheels似乎是没有根据的:

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

What is the correct way of achieving runtime multiple inheritance using impromptu-interface?使用即兴接口实现运行时多重继承的正确方法是什么?

The issues you are running into are all related to type safety--even when using a library like Impromptu, you have to be sure the compiler and the runtime are sure the object you are passing into the method is the type that method requires.您遇到的问题都与类型安全有关——即使使用像 Impromptu 这样的库,您也必须确保编译器和运行时确定您传递给方法的对象是方法所需的类型。

ActLike<T> can implement many interfaces, but it only returns a single typed instance of T , so without a type that tells the compiler that your instance implements several interfaces, you will be forced to cast to the necessary interfaces. ActLike<T>可以实现许多接口,但它只返回T的单个类型化实例,因此如果没有一个类型告诉编译器您的实例实现了多个接口,您将被迫转换为必要的接口。

Also, ImpromptuInterface allows you to wrap an object with an interface that informally matches up with the implementation of that object, even if the interface was not formally declared.此外,ImpromptuInterface 允许您使用与该对象的实现非正式匹配的接口包装对象,即使该接口未正式声明。 As a consumer of that library, you still have to provide the implementations for the library to wrap.作为该库的使用者,您仍然必须为要包装的库提供实现。

Try something like the following:尝试类似以下内容:

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

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

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