- C# code
[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)//[color=#FF0000]这个泛型怎么解释我不太懂[/color] 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))// if (attribute.Type.GetInterfaces().Contains(typeof(T))) return (T)attribute.Injector; return null; }} [Decorator(typeof(ITimeProvider)]//[color=#FF0000]这里应该使用可实例化的类吧,不应该使用接口吧[/color]class Client{ public int GetYear() { ITimeProvider provider = AttributeHelper.Injector(this); return provider.CurrentDate.Year; }}
这段代码是依赖注入。使用Attribute把外部对接口的实现注入到类中。通过修改Attribute来改变依赖。
其中第29行和第35行中,有一个明显的错误。
先从第35行说起
[Decorator(typeof(ITimeProvider)]
这行代码说明要注入ITimeProvider类型,但是我们知道接口是不能被直接实例化的。所以这里的ITimeProvider应该改成TimeProvider。
但是这个时候第29行的条件判断就出现问题了,因为我们要得到的是ITimeProvider,而Decorator给的参数是TimeProvider,这两个类型是不会相等的。
这个时候我们还必须修改第29行的代码为
if (attribute.Type.GetInterfaces().Contains(typeof(T)))
通过寻找实现接口的实例,才能够真正找到我们要的Decorator。
------解决方案--------------------
[Decorator(typeof(ITimeProvider)]
这里定义接口是没错的。DI通过接口引入外部实现,思想没错。
关键在于:(new Assembler()).Create(this.type);
是怎么实现的 Create 方法。里面应该有真正引入外部实例的地方。