今天读王翔的《设计模式 - 基于C#的工程化实现及扩展》,刚把第一章读完。作为一个C#初学者和工作者,发现了55页,也就是第一章的最后一段关于依赖注入的实例代码中有一个很明显的错误。本来想直接联系作者的,可是实在找不到他的联系方式,就发在自己博客上了。如果同样读过这本书的人能看到,不胜荣幸。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
[AttributeUsage(AttributeTargets.Class), AllowMultiple=true] sealed class DecoratorAttribute : Attribute { public readonly object Injector; private Type type; public DecoratorAttribute(Type type) { if (type == null) throw new ArgumentNullException("type"); this.type = type; Injector = (new Assembler()).Create(this.type); } public Type Type { get { return this.type; } } } static class AttributeHelper { public static T Injector(object target) where T : class { if (target == null) throw new ArgumentNullException("target"); Type targetType = target.GetType(); object[] attributes = targetType.GetCustomAttributes( typeof(DecoratorAttribute), false); if ((attributes == null) || (attributes.Length <= 0)) return null; foreach (DecoratorAttribute attribute in (DecoratorAttribute [])attributes) if (attribute.Type == typeof(T)) return (T)attribute.Injector; return null; } } [Decorator(typeof(ITimeProvider)] class Client { public int GetYear() { ITimeProvider provider = AttributeHelper.Injector(this); return provider.CurrentDate.Year; } } |
这段代码是依赖注入。使用Attribute把外部对接口的实现注入到类中。通过修改Attribute来改变依赖。
其中第29行和第35行中,有一个明显的错误。
先从第35行说起
1 |
[Decorator(typeof(ITimeProvider)] |
这行代码说明要注入ITimeProvider类型,但是我们知道接口是不能被直接实例化的。所以这里的ITimeProvider应该改成TimeProvider。
但是这个时候第35行的条件判断就出现问题了,因为我们要得到的是ITimeProvider,而Decorator给的参数是TimeProvider,这两个类型是不会相等的。
这个时候我们还必须修改第35行的代码为
1 |
if (attribute.Type.GetInterfaces().Contains(typeof(T))) |
通过寻找实现接口的实例,才能够真正找到我们要的Decorator。