如果仅仅是为了分离依赖耦合,那还不如直接用反射来的简单痛快,两三行代码就搞定。作为一个框架,Unity 还能为我们完成更多的任务,比如自动创建依赖对象。
1. 构造注入如果注册的类型构造方法参数中需要依赖其他自定义类型,那么 Unity 会在你调用 Resolve 时自动生成,并传递给目标构造参数。
Code
public class Data
{
public Data()
{
Console.WriteLine("Data constructor");
}
}
public interface ICache
{
Data Data { get; set; }
}
public class MemoryCache : ICache
{
public MemoryCache(Data data)
{
this.Data = data;
}
public Data Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ICache, MemoryCache>();
var cache = container.Resolve<ICache>();
Console.WriteLine(cache.Data != null);
}
}
输出:
Data constructor...
True
如果注册类型有多个构造方法时,我们可以用 InjectionConstructorAttribute 特性告知容器如何选择。
Code
public class MemoryCache : ICache
{
public MemoryCache()
{
Console.WriteLine("Constructor1");
}
[InjectionConstructor]
public MemoryCache(Data data)
{
Console.WriteLine("Constructor2");
}
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ICache, MemoryCache>();
var cache = container.Resolve<ICache>();
}
}
输出:
Constructor2...
如果不使用 InjectionConstructorAttribute,那么 Unity 默认会选择参数最多的那个构造方法。
Code
public class MemoryCache : ICache
{
public MemoryCache()
{
Console.WriteLine("Constructor1");
}
public MemoryCache(Data data, Data data2)
{
Console.WriteLine("Constructor3");
}
public MemoryCache(Data data)
{
Console.WriteLine("Constructor2");
}
public Data Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ICache, MemoryCache>();
var cache = container.Resolve<ICache>();
}
}
输出:
Constructor3...
而如果有多个 "参数最多" 的构造方法时,那么就等着抛异常后改代码吧。o(∩_∩)o...
2. 属性注入同样使用一个特性 DependencyAttribute,我们可以让容器自动替我们完成属性赋值操作。
Code
public class Data
{
public Data()
{
Console.WriteLine("Data constructor");
}
}
public interface ICache
{
Data Data { get; set; }
}
public class MemoryCache : ICache
{
[Dependency]
public Data Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ICache, MemoryCache>();
var cache = container.Resolve<ICache>();
Console.WriteLine(cache.Data != null);
}
}
输出:
Data constructor...
True
如果属性的类型已经在容器内注册,那么我们还可以使用 Dependency(name) 挑选合适的目标类型进行构造。
Code
public interface IData { }
public class Data1 : IData
{
public Data1()
{
Console.WriteLine("Data1 constructor");
}
}
public class Data2 : IData
{
public Data2()
{
Console.WriteLine("Data2 constructor");
}
}
//--------------------------------------------
public interface ICache
{
IData Data { get; set; }
}
public class MemoryCache : ICache
{
[Dependency("data2")]
public IData Data { get; set; }
}
//--------------------------------------------
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().
RegisterType<ICache, MemoryCache>().
RegisterType<IData, Data1>("data1").
RegisterType<IData, Data2>("data2");
var cache = container.Resolve<ICache>();
Console.WriteLine(cache.Data != null);
}
} 输出:
Data2 constructor...
True
3. 方法注入方法注入更像一个被自动调用的初始化操作,当然这个方法也可以像构造方法那样拥有依赖类型参数。
Code
public class Data
{
public Data()
{
Console.WriteLine("Data constructor");
}
}
public interface ICache
{
Data Data { get; set; }
void Initialize(Data data);
}
public class MemoryCache : ICache
{
public Data Data { get; set; }
[InjectionMethod]
public void Initialize(Data data)
{
this.Data = data;
Console.WriteLine("Initialize");
}
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().
RegisterType<ICache, MemoryCache>();
var cache = container.Resolve<ICache>();
Console.WriteLine(cache.Data != null);
}
}
输出:
Data constructor...
Initialize...
True
我们还可以利用 DependencyAttribute 特性指定方法(含构造方法)参数的注入类型。
Code
public interface IData { }
public class Data1 : IData
{
public Data1()
{
Console.WriteLine("Data1 constructor");
}
}
public class Data2 : IData
{
public Data2()
{
Console.WriteLine("Data2 constructor");
}
}
//--------------------------------------------
public interface ICache
{
IData Data { get; set; }
void Initialize(IData data);
}
public class MemoryCache : ICache
{
public IData Data { get; set; }
[InjectionMethod]
public void Initialize([Dependency("data2")]IData data)
{
this.Data = data;
Console.WriteLine("Initialize");
}
}
//--------------------------------------------
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().
RegisterType<ICache, MemoryCache>().
RegisterType<IData, Data1>("data1").
RegisterType<IData, Data2>("data2");
var cache = container.Resolve<ICache>();
Console.WriteLine(cache.Data != null);
}
}
输出:
Data2 constructor...
Initialize...
True