我正试图从这个截屏视频中学习IOC原理 Inversion of Control from First Principles - Top Gear Style
我尝试按照截屏播放但我在 AutomaticFactory 尝试创建 AutoCue 的对象时出错。 AutoCue类有contructor,它接受IClock而不是 SystemClock 。但我的问题是,在截屏 IClock 中使用 SystemClock 解决了内部 AutomaticFactory 。但在我的代码中, IClock 没有得到解决。我错过了什么吗?
class Program
{
static void Main(string[] args)
{
//var clarkson = new Clarkson(new AutoCue(new SystemClock()), new Megaphone());
//var clarkson = ClarksonFactory.SpawnOne();
var clarkson = (Clarkson)AutomaticFactory.GetOne(typeof(Clarkson));
clarkson.SaySomething();
Console.Read();
}
}
public class AutomaticFactory
{
public static object GetOne(Type type)
{
var constructor = type.GetConstructors().Single();
var parameters = constructor.GetParameters();
if (!parameters.Any()) return Activator.CreateInstance(type);
var args = new List<object>();
foreach(var parameter in parameters)
{
var arg = GetOne(parameter.ParameterType);
args.Add(arg);
}
var result = Activator.CreateInstance(type, args.ToArray());
return result;
}
}
public class Clarkson
{
private readonly AutoCue _autocue;
private readonly Megaphone _megaphone;
public Clarkson(AutoCue autocue,Megaphone megaphone)
{
_autocue = autocue;
_megaphone =megaphone;
}
public void SaySomething()
{
var message = _autocue.GetCue();
_megaphone.Shout(message);
}
}
public class Megaphone
{
public void Shout(string message)
{
Console.WriteLine(message);
}
}
public interface IClock
{
DateTime Now { get; }
}
public class SystemClock : IClock
{
public DateTime Now { get { return DateTime.Now; } }
}
public class AutoCue
{
private readonly IClock _clock;
public AutoCue(IClock clock)
{
_clock = clock;
}
public string GetCue()
{
DateTime now = _clock.Now;
if (now.DayOfWeek == DayOfWeek.Sunday)
{
return "Its a sunday!";
}
else
{
return "I have to work!";
}
}
}
答案 0 :(得分:4)
您基本上实现的是一个小型IoC容器,它能够自动连接对象图。但是您的实现只能创建具体对象的对象图。这会使您的代码违反Dependency Inversion Principle。
实现中缺少的是某种Register
方法告诉你的AutomaticFactory
,当面对抽象时,它应该解决注册的实现。这看起来如下:
private static readonly Dictionary<Type, Type> registrations =
new Dictionary<Type, Type>();
public static void Register<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
registrations.Add(typeof(TService), typeof(TImplementation));
}
不,您也必须对GetOne
方法进行调整。您可以在GetOne
方法的开头添加以下代码:
if (registrations.ContainsKey(type))
{
type = registrations[type];
}
这将确保如果提供的type
在AutomaticFactory
中注册为TService
,则将使用映射的TImplementation
,并且工厂将继续使用此实现要建立的类型。
但这确实意味着您现在必须明确注册IClock
和SystemClock
之间的映射(如果您正在使用IoC容器,这是很自然的事情)。您必须在从AutomaticFactory
解析第一个实例之前进行此映射。因此,您应该将以下行添加到Main
方法的开头:
AutomaticFactory.Register<IClock, SystemClock>();