C# 具有即兴接口的运行时多重继承
我正试图使用即兴接口让运行时多重继承工作,但当我想将对象传递给方法时,我被卡住了C# 具有即兴接口的运行时多重继承,c#,inheritance,runtime,multiple-inheritance,impromptu-interface,C#,Inheritance,Runtime,Multiple Inheritance,Impromptu Interface,我正试图使用即兴接口让运行时多重继承工作,但当我想将对象传递给方法时,我被卡住了 public interface IEngine { void Foo(); } public interface IWheels { void Foo(); } public interface IChassie { void Foo(); } public interface IPaintShop { void PaintWheels(IWheels wheels);
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
System.InvalidCastException:无法强制转换类型为的对象
“ImpromptuInterface.ActLikeCaster”以键入
“MyStuff.IWheels”
以下方法可行,但我不确定这是否正确;当IWheels
接口应已被继承时,将汽车转换为IWheels
似乎是不必要的:
var wheels = Impromptu.CoerceConvert(car, typeof (IWheels));
paintShop.PaintWheels(wheels);
使用impromptu接口实现运行时多重继承的正确方法是什么?您遇到的问题都与类型安全相关——即使使用类似impromptu的库,您也必须确保编译器和运行时确保传递到方法中的对象是方法所需的类型
ActLike
可以实现许多接口,但它只返回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();
}
}
}
使用系统;
使用Impromptu接口;
使用ImpromptuInterface.Dynamic;
名称空间示例
{
公共接口引擎
{
void Foo();
}
公共接口IWheels
{
void Foo();
}
公共接口IChassie
{
void Foo();
}
公共接口商店
{
空漆轮(带轮);
空漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆漆;
真空镀铬发动机(内燃机);
}
内部课程计划
{
公共静态void Main(字符串[]args)
{
var ps=新
{
PaintWheels=ReturnVoid.Arguments(wheels=>wheels.Foo()),
PaintChassie=ReturnVoid.Arguments(chassie=>chassie.Foo()),
ChromeEngine=ReturnVoid.Arguments(引擎=>engine.Foo())
};
var paintShop=ps.ActLike();
var fullCar=新
{
Foo=ReturnVoid.Arguments(()=>Console.WriteLine(“helloworld!”)
};
var car=fullCar.ActLike(typeof(IChassie),typeof(IWheels));
//这3个调用中的每一个都会将“Hello World!”打印到控制台
paintShop.PaintWheels((IWheels)car);//需要告诉编译器将您的汽车强制转换为IWheels类型,因为var car的类型是IEngine
paintShop.PaintChassie(carasichassie);//需要告诉编译器将您的汽车转换为IChassie类型,因为var car的类型是IEngine
paintShop.ChromeEngine(car);//由于var car是IEngine类型,所以无需铸造即可工作
//这3个调用中的每一个都会在控制台上打印“Hello World!”
动态car=汽车;
paintShop.PaintWheels(dynamicCar);//使用dynamic可以禁用编译时
paintShop.PaintChassie(dynamicCar);//类型检查和编译器在类型上“信任您”
paintShop.ChromeEngine(dynamicCar);//由于即兴包装了对象并为您实现了接口,所以没有运行时异常
Console.ReadLine();
}
}
}
ICar接口定义是什么样子的?@AGB我现在已经添加了它。在本例中不多。您的意思是让IEngine
、IWheels
和iCassie
不相关吗?您在文章中提到它们应该被继承,但正如所写的,它们根本不会相互继承。@AGB我试图在运行时实现多重继承。我试图在编译时执行的操作与以下代码类似:抽象类Car:IEngine,IWheels,iCassie{/..Foo}
谢谢,但是公共接口ICar:iCassie,IWheels,IEngine
在您的代码中意味着编译时多重继承而不是运行时。更新了我的答案以删除公共接口ICar:iCassie、IWheels、IEngine{}
谢谢。似乎fullCar也可以是任何对象,不需要匿名。是的,对我来说这似乎是正确的。我对ImpromptuInterface库不是很熟悉,但文档中提到了包装任何对象、POCO或动态的能力,因此我认为只要您尝试实现的接口有足够的非正式实现,您就可以开始了。
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();
}
}
}