带有临时接口的运行时多重继承
Runtime multiple inheritance with impromptu-interface
我正在尝试使用临时接口让运行时多重继承工作,但是当我想将对象传递给方法时我遇到了困难。
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
我试过投射但得到 InvalidCastException
:
paintShop.PaintWheels((IWheels)car);
System.InvalidCastException : Unable to cast object of type
'ImpromptuInterface.ActLikeCaster' to type
'MyStuff.IWheels'.
下面的方法可行,但我不确定这是正确的方法;当 IWheels
接口应该已经被继承时,将 car 转换为 IWheels
似乎是没有根据的:
var wheels = Impromptu.CoerceConvert(car, typeof (IWheels));
paintShop.PaintWheels(wheels);
使用即兴接口实现运行时多重继承的正确方法是什么?
您 运行 遇到的问题都与类型安全有关——即使在使用像 Impromptu 这样的库时,您也必须确保编译器和运行时确保您传递给方法是方法需要的类型。
ActLike<T>
可以实现许多接口,但它只是 returns T
的单个类型实例,因此如果没有类型告诉编译器您的实例实现了多个接口,您将被迫投射到必要的接口。
此外,ImpromptuInterface 允许您 wrap 具有与该对象的实现非正式匹配的接口的对象,即使该接口未正式声明也是如此。作为该库的使用者,您仍然必须提供要包装的库的实现。
尝试如下操作:
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();
}
}
}
我正在尝试使用临时接口让运行时多重继承工作,但是当我想将对象传递给方法时我遇到了困难。
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
我试过投射但得到 InvalidCastException
:
paintShop.PaintWheels((IWheels)car);
System.InvalidCastException : Unable to cast object of type 'ImpromptuInterface.ActLikeCaster' to type 'MyStuff.IWheels'.
下面的方法可行,但我不确定这是正确的方法;当 IWheels
接口应该已经被继承时,将 car 转换为 IWheels
似乎是没有根据的:
var wheels = Impromptu.CoerceConvert(car, typeof (IWheels));
paintShop.PaintWheels(wheels);
使用即兴接口实现运行时多重继承的正确方法是什么?
您 运行 遇到的问题都与类型安全有关——即使在使用像 Impromptu 这样的库时,您也必须确保编译器和运行时确保您传递给方法是方法需要的类型。
ActLike<T>
可以实现许多接口,但它只是 returns T
的单个类型实例,因此如果没有类型告诉编译器您的实例实现了多个接口,您将被迫投射到必要的接口。
此外,ImpromptuInterface 允许您 wrap 具有与该对象的实现非正式匹配的接口的对象,即使该接口未正式声明也是如此。作为该库的使用者,您仍然必须提供要包装的库的实现。
尝试如下操作:
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();
}
}
}