[英]C# polymorphous design without casting
我有Generator类,可以生成具有不同概率的不同接口的对象。 Generator生成的所有对象的类型都是BaseClass
。 BaseClass
是一个抽象基类。
可以说接口是I1
, I2
我还有另一个类Resolver
,该类具有两个接口的多态方法,如下所示:
Resolve(I1 myObj){//code for I1}
Resolve(I2 myObj){//code for I2}
主类如下所示: BaseClass event = Generator.generate(); //event is implements I1 or I2. Not known what interfaces until run time. Resolver.Resolve(event); //Here i got an error, because event is BaseClass type and not I1 or I2 type.
BaseClass event = Generator.generate(); //event is implements I1 or I2. Not known what interfaces until run time. Resolver.Resolve(event); //Here i got an error, because event is BaseClass type and not I1 or I2 type.
有没有解决此问题的方法,而无需显式检查接口类型并将其强制转换为适当的接口。 我来自python背景,因此静态类型语言对我来说是新的。
考虑使用依赖项注入来允许事件对象调用解析程序本身。
public interface IResolvable
{
void Resolve(Resolver resolver);
}
public interface I1 : IResolvable { //... }
public interface I2 : IResolvable { //... }
public class Resolver
{
public void Resolve(I1 i) { //... }
public void Resolve(I2 i) { //... }
}
public abstract class BaseClass : IResolvable
{
public abstract void Resolve(Resolver resolver);
//...
}
一个实现看起来像:
public class Implementation1 : BaseClass, I1
{
public override void Resolver(Resolver resolver)
{
resolver.Resolve(this);
}
//...
}
然后调用它:
Resolver resolver = new Resolver();
IResolvable evnt = Generator.Generate();
evnt.Resolve(resolver);
我们可以更进一步,为Resolver创建一个接口,以便为单元测试目的而对其进行模拟,并充分利用DI模式。
public interface IResolver
{
void Resolve(I1 i) { //... }
void Resolve(I2 i) { //... }
}
然后我们更改IResolvable的定义
public interface IResolvable
{
void Resolve(IResolver resolver);
}
编辑 我调整了答案,因为我第一次没有正确理解问题。
我认为,如果不使用强制转换,就无法完全实现您想要的目标。 据我了解,一旦您通过Generator.generate()
的基类型引用了该对象,就无法通过其专用类型再次访问该对象而不进行转换。
我可以想到两种可能对您有趣的选择。 一种使用C#7模式匹配(有点像使用强制转换),另一种使用dynamic
。
模式匹配
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(IEvent theEvent)
{
switch (theEvent)
{
case Event1 e1: Resolve(e1); break;
case Event2 e2: Resolve(e2); break;
default: throw new ArgumentException("not a recognized type", nameof(theEvent));
}
}
private void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
private void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
var event1 = generator.Generate();
var event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}
Dynamic
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
public void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
dynamic event1 = generator.Generate();
dynamic event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}
这是一些代码,演示了不需要强制转换的虚函数方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
interface IBase
{
void Function();
}
class BaseClass : IBase
{
public virtual void Function()
{
}
}
interface I1: IBase
{
}
interface I2 : IBase
{
}
class C1: BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C1");
}
}
class C2 : BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C2 !!!");
}
}
static class Generator
{
public static BaseClass generateC1()
{
return new C1();
}
public static BaseClass generateC2()
{
return new C2();
}
}
class Program
{
static void Main(string[] args)
{
BaseClass b1 = Generator.generateC1();
b1.Function();
Console.WriteLine("-------");
BaseClass b2 = Generator.generateC2();
b2.Function();
Console.WriteLine("End!");
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.