Kar*_*ala 2 c# polymorphism switch-statement
我正在阅读本文以删除c#中的切换案例并使用多态来实现它.
https://refactoring.guru/replace-conditional-with-polymorphism
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Consolas
{
public class Program
{
static void Main(string[] args)
{
var animalType = "Dog"; //consider this as an argument supplied to the app
//How to create dynamic instance for IAnimal ???
//Is Activator.CreateInstance the only way to achieve it ??
//IAnimal animal = ..what here ?
//animal.Bark();
}
}
public interface IAnimal
{
void Bark();
}
public class Dog: IAnimal
{
public void Bark()
{
Console.WriteLine("Bow Bow");
}
}
public class Cat: IAnimal
{
public void Bark()
{
Console.WriteLine("Meow Meow");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如何为该接口创建实例,以便它可以动态调用该Bark方法.
有人可以提供最好的方法,而不仅仅是一个解决方案.
考虑使用工厂模式来实现这一点,一个例子是这样的:
public class AnimalFactory
{
public IAnimal CreateAnimal(string animalType)
{
//Here you can either have a switch statement checking for
//type, or use Type.GetType(animalType) and then create an
//instance using the Activator - but in the latter case you will
//need to pass in the exact type name of course
//PS. You can also use an IoC container to resolve all
//implementations of IAnimal and have a distinguishing property
//that you use here to select the type you want, but I think
//that's a bit off topic so won't detail it here
}
}
static void Main(string[] args)
{
var animalType = "Dog";
var amimal = new AnimalFactory().CreateAnimal(animalType);
animal.Bark();
}
Run Code Online (Sandbox Code Playgroud)
编辑
使用IoC容器(本例中为AutoFac)的一种方法是扫描程序集并注册IAnimal由类名称键入的所有实现(如果您注册单例实例,则可以通过接口的属性键入),类似于以下:
class Program
{
public static IContainer _container;
static void Main(string[] args)
{
//Register types
Register();
//Resolve a dog
var dog = _container.ResolveKeyed<IAnimal>("Dog");
//Resolve a cat
var cat = _container.ResolveKeyed<IAnimal>("Cat");
dog.Bark(); //Bow Bow
cat.Bark(); //Meow Meow
Console.Read();
}
static void Register()
{
//Get all types implementing IAnimal, you can of course scan multiple assemblies,
//here I am only looking at the current assembly
var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => !t.IsInterface && t.IsAssignableTo<IAnimal>());
var builder = new ContainerBuilder();
foreach (var t in types)
{
//Use the type name as a key to the instance
builder.RegisterType(t).Keyed<IAnimal>(t.Name)
.InstancePerDependency(); //You want a new instance each time you resolve
}
_container = builder.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
当然,您仍然可以将其重构为工厂PS.使用AutoFac的程序集扫描可能有更好的方法在程序集中注册所有类型,但我看不出任何方法将其与每种类型的键组合.