DryIoc框架中关于类型定义两个术语: Implementaion Type (“实现类”) 与 Service Type (”服务类“) 。简单来说,Service Type 通常是指抽象类或接口,Implementation Type 是 Service Type 的实现类。

注册 API

示例 :注册“服务类”与“实现类”之间的一一映射

  1. // 支持编译时类型
  2. class Register_service_with_implementation_types
  3. {
  4. [Test]
  5. public void Example()
  6. {
  7. var container = new Container();
  8. container.Register<IClient, SomeClient>();
  9. container.Register<IService, SomeService>();
  10. }
  11. }
  12. // 支持运行时类型,通过传入 Type 类型参数
  13. class Register_service_with_implementation_runtime_types
  14. {
  15. [Test]
  16. public void Example()
  17. {
  18. var container = new Container();
  19. container.Register(typeof(IClient), typeof(SomeClient));
  20. container.Register(typeof(IService), typeof(SomeService));
  21. }
  22. }
  23. // 支持泛型
  24. class Register_open_generic_service_with_implementation_runtime_types
  25. {
  26. interface IService<T> { }
  27. class SomeService<T> : IService<T> { }
  28. [Test]
  29. public void Example()
  30. {
  31. var container = new Container();
  32. container.Register(typeof(IService<>), typeof(SomeService<>));
  33. // 支持自动识别泛型的类型参数 T
  34. var s = container.Resolve<IService<string>>();
  35. Assert.IsInstanceOf<SomeService<string>>(s);
  36. }
  37. }
  38. // 支持将“实现类” 注册为 ”服务类”
  39. class Register_implementation_as_service_type
  40. {
  41. [Test]
  42. public void Example()
  43. {
  44. var container = new Container();
  45. container.Register<SomeService>();
  46. // or via run-time type
  47. container.Register(typeof(SomeService));
  48. }
  49. }

最顶层的注册 API

Container 类所有的 Register 重载方法最终都是在调用该接口方法。

  • 从 IRegistrator.Register 方法的声明可知,“服务类”作为直接参数,而“实现类”并不作为直接参数

    1. public interface IRegistrator
    2. {
    3. //..
    4. void Register(Factory factory, Type serviceType, object serviceKey, IfAlreadyRegistered? ifAlreadyRegistered, bool isStaticallyChecked);
    5. }

    Register 源码:

  • 从DryIoc 源码可知,“实现类”是作为 Factory 类的构造函数的参数

    1. // DryIco源码:src/DryIoc/Container.cs
    2. public static void Register<TService, TImplementation>(this IRegistrator registrator,
    3. IReuse reuse = null, Made made = null, Setup setup = null, IfAlreadyRegistered? ifAlreadyRegistered = null,
    4. object serviceKey = null)
    5. where TImplementation : TService =>
    6. registrator.Register(new ReflectionFactory(typeof(TImplementation), reuse, made, setup),
    7. typeof(TService), serviceKey, ifAlreadyRegistered, isStaticallyChecked: true);

    Factory 类

    Factory 类,使用不同的方式实例化服务对象,Register 方法 默认使用的是 ReflectionFactory 。

DryIoc 一共提供了三种 Factory类型,分别是:

  • ReflectionFactory:根据类型进行反射构建对象。
  • DelegateFactory:根据委托方法构建对象。
  • ExpressionFactory:根据表达式构建对象。

    IReuse 接口

    IReuse 接口,用于简化对象复用策略。

使用例子:

  • 在构建 Factory 类对象时,可通过传入Reuse.Singleton 对象(Singleton 单例模式)。
  • Reuse.Singleton 本质是 IReuse 接口类型的静态实例。
    1. container.Register(typeof(IA), new ReflectionFactory(typeof(A), Reuse.Singleton));
    SingletonReuse 源码: ```csharp // DryIco源码:src/DryIoc/Container.cs public sealed class SingletonReuse : IReuse {…}

// DryIco源码:src/DryIoc/Container.cs public static class Reuse { ///

Specifies to store single service instance per . public static readonly IReuse Singleton = new SingletonReuse(); }

  1. <a name="xl69m"></a>
  2. # 注册单例模式
  3. 在上述例子中,注册时并不关注服务对象的生命周期,意味着这些服务实例l都是瞬时(Transient)—— 每次解析注入时都要要创建一个服务实例。
  4. 注意:通常,容器的生命周期与程序的生命周期保持一直。
  5. DryIoc 支持通过 Reuse 与 Scopes 实现单例模式。
  6. <a name="xzuuI"></a>
  7. #### 示例 :单例模式
  8. ```csharp
  9. class Singleton_service_registration
  10. {
  11. [Test]
  12. public void Example()
  13. {
  14. var container = new Container();
  15. container.Register<IClient, SomeClient>();
  16. // 这里使用 Reuse.Singleton 将该注册类型声明为 单例模式
  17. container.Register<IService, SomeService>(Reuse.Singleton);
  18. var one = container.Resolve<IClient>();
  19. var two = container.Resolve<IClient>();
  20. Assert.AreSame(two.Service, one.Service);
  21. }
  22. }

注册多个服务类型

DryIoc 支持两种方式用于注册多个服务类型:默认注册方式、携带Key注册方式。

默认注册方式

示例 :注册“服务类”与“实现类”之间的一对多映射。

  1. class Multiple_default_registrations
  2. {
  3. internal interface ICommand { }
  4. internal class GetCommand : ICommand { }
  5. internal class SetCommand : ICommand { }
  6. internal class DeleteCommand : ICommand { }
  7. [Test]
  8. public void Example()
  9. {
  10. var container = new Container();
  11. // 依次为 ICommand 注册3个类型
  12. container.Register<ICommand, GetCommand>();
  13. container.Register<ICommand, SetCommand>();
  14. container.Register<ICommand, DeleteCommand>();
  15. // Assert通过,执行代码抛出错误,因为 ICommand 接口已注册了三个“实现类”,导致 container 无法判断解析对象的类型
  16. Assert.Throws<ContainerException>(() =>
  17. container.Resolve<ICommand>());
  18. // 注册了多个“实现类”时,解析对象可以使用集合进行封装,例如IEnumberable<T>。
  19. var commands = container.Resolve<IEnumerable<ICommand>>();
  20. // 集合中的每一项都与对应一种“实现类”,集合数量等于注册的“实现类”的数量。
  21. Assert.AreEqual(3, commands.Count());
  22. // 直接使用 ResolveMany 方法,即可直接解析出集合类型,默认返回类型为 IEnumerable<T>
  23. var commands2 = container.ResolveMany<ICommand>();
  24. Assert.AreEqual(3, commands2.Count());
  25. }
  26. }

DryIoc默认支持的集合类型:

  • IEnumerable (默认)
  • T[]
  • IList
  • ICollection
  • IReadOnlyList
  • IReadOnlyCOllection
    • 通过手动设置集合类型,可更改解析集合类型,例如:(除了IEnumerable外,其余接口类型均解析出数组类型Array )
      1. // 解析出数组集合
      2. var commands1 = container.Resolve<ICommand[]>();
      3. var commands2 = container.Resolve<IList<ICommand>>();
      4. var commands3 = container.Resolve<ICollection<ICommand>>();
      5. var commands4 = container.Resolve<IReadOnlyList<ICommand>>();
      6. var commands5 = container.Resolve<IReadOnlyCOllection<ICommand>>();
      为了方便,DryIoc 定义了专用的、包含默认参数的ResolveMany方法。
      为了在内部存储这些注册信息,DryIoc 使用了 DefaultKey 类型作为 Key。

注意:集合中解析对象的顺序与注册类型的顺序保持一致。

如何使 Resolve 方法不引发异常

在注册多个类型的前提下,直接使用 Resolve 方法会引发错误。

  1. var commands0 = container.Resolve<ICommand>();

异常信息 :
DryIoc.ContainerException:“code: Error.ExpectedSingleDefaultFactory;
message: Expecting a single default registration but found many:
(DefaultKey(0), {FactoryID=144, ImplType=ConsoleApp1.GetCommand}),
(DefaultKey(1), {FactoryID=145, ImplType=ConsoleApp1.SetCommand}),
(DefaultKey(2), {FactoryID=146, ImplType=ConsoleApp1.DeleteCommand})
when resolving resolution root ConsoleApp1.ICommand
from container without scope.
Please identify service with key, or metadata, or use Rules.WithFactorySelector to specify single registered factory.”

以下几类方法可使得 Resolve 某个特定类型服务实例而不引发异常:

  • 使用条件:container.Regsiter(setup: Setup.With(condition: req => req.IsResolutionRoot )),其他剩下的注册信息则被指定为相反的参数,如: req => !req.IsResolutionRoot。
  • 使用元类型(例如 ComandId 枚举)以及解析为 Meta<,>包装器:container.Register(setup: Setup.With(metadata: CommandId.Get));解析时如下:container.Resolve>>().Where(m => (m.Metadata==Command.Get))。
  • 使用特定的作用域
  • 注册时携带 Key

携带Key注册方式

在注册时可通过提供 Service Key来区分不同的实现类。Service Key 可以是任意实现了 Object.GetHashCode 和 Object.Equals 的类型。通常使用枚举,字符串或者数字。

标记“服务类”:serviceKey参数

IRegistrator.sRegister 方法中,serviceKey 参数用于在 DryIoc 中唯一标识“服务类”:

  1. public interface IRegistrator
  2. {
  3. //..
  4. void Register(Factory factory, Type serviceType, object serviceKey, IfAlreadyRegistered? ifAlreadyRegistered, bool isStaticallyChecked);
  5. }

从 Container 源码中可知,在serviceKey 为空时,使用 Rules.DefaultRegistrationServiceKey 属性作为 serviceKey 值:

  1. public partial class Container : IContainer
  2. {
  3. public void Register(Factory factory, Type serviceType, object serviceKey, IfAlreadyRegistered? ifAlreadyRegistered, bool isStaticallyChecked)
  4. {
  5. //..
  6. if (serviceKey == null)serviceKey = Rules.DefaultRegistrationServiceKey;
  7. }
  8. //..
  9. }

DryIoc 默认情况下使用 DefaultKey 类作为 serviceKey 参数:

  • DefaultKey 类中的 RegistrationOrder 属性(int),主要用于对“实现类”排序。
  • DefaultKey 类覆写了 Object.GetHasCode 和 Object.Equals 方法。 ```csharp // DryIco源码:src/DryIoc/Container.cs

///

Used to represent multiple default service keys. /// Exposes to determine order of service added. public sealed class DefaultKey : IConvertibleToExpression { /// Allows to determine service registration order. public readonly int RegistrationOrder;

  1. /// <summary>Compares keys based on registration order. The null (represents default) key is considered equal.</summary>
  2. public override bool Equals(object key) => key == null || (key as DefaultKey)?.RegistrationOrder == RegistrationOrder;
  3. /// <summary>Returns registration order as hash.</summary>
  4. public override int GetHashCode() => RegistrationOrder;
  5. // onther Code
  6. // .....

}

  1. <a name="1o8zQ"></a>
  2. #### 示例 :注册时提供 Service Key
  3. 设置 serviceKey 参数手动标记“实现类”
  4. - Register 方法的 serviceKey 参数接受一个 object 类型对象,该对象需要实现 Object.GetHasCode 和 Object.Equals 方法,通常该参数会使用**枚举,字符串或者数值**。
  5. - 未提供 serviceKey 参数时,默认使用了 DefaultKey 类型对象,该类覆写了 Object.GetHasCode 和 Object.Equals 方法。
  6. ```csharp
  7. class Multiple_keyed_registrations
  8. {
  9. internal interface ICommand { }
  10. internal class GetCommand :唯一标记 ICommand { }
  11. internal class SetCommand : ICommand { }
  12. internal class DeleteCommand : ICommand { }
  13. enum CommandId { Get, Set, Delete }
  14. [Test]
  15. public void Example()
  16. {
  17. var container = new Container();
  18. container.Register<ICommand, GetCommand>(serviceKey: CommandId.Get);
  19. container.Register<ICommand, SetCommand>(serviceKey: CommandId.Set);
  20. container.Register<ICommand, DeleteCommand>(serviceKey: CommandId.Delete);
  21. // 这里通过 serviceKey 指定解析的类型
  22. var setCommand = container.Resolve<ICommand>(serviceKey: CommandId.Set);
  23. Assert.IsInstanceOf<SetCommand>(setCommand);
  24. // 解析所有类型到结合中
  25. var commands = container.Resolve<ICommand[]>();
  26. Assert.AreEqual(3, commands.Length);
  27. // 这里通过 Behaviro 将解析集合类型设为固定长度的数组
  28. var commands2 = (ICommand[])container.ResolveMany<ICommand>(behavior: ResolveManyBehavior.AsFixedArray);
  29. Assert.AreEqual(3, commands2.Length);
  30. }
  31. }

还有一种方法用于读取各自的 Key。它与 Lazy 或者 Func 包装器结合起来特别好用,尤其是针对菜单或导航这类UI需求。

示例 :获取注册信息的 Service Key

  1. class Resolve_commands_with_keys
  2. {
  3. internal interface ICommand { }
  4. internal class GetCommand : ICommand { }
  5. internal class SetCommand : ICommand { }
  6. internal class DeleteCommand : ICommand { }
  7. enum CommandId { Get, Set, Delete }
  8. [Test]
  9. public void Example()
  10. {
  11. var container = new Container();
  12. container.Register<ICommand, GetCommand>(serviceKey: CommandId.Get);
  13. container.Register<ICommand, SetCommand>(serviceKey: CommandId.Set);
  14. container.Register<ICommand, DeleteCommand>(serviceKey: CommandId.Delete);
  15. var commands = container.Resolve<KeyValuePair<CommandId, ICommand>[]>();
  16. Assert.AreEqual(CommandId.Get, commands[0].Key);
  17. // or as Lazy
  18. var lazyCommands = container.Resolve<KeyValuePair<CommandId, Lazy<ICommand>>[]>();
  19. Assert.AreEqual(CommandId.Set, lazyCommands[1].Key);
  20. // or as Func
  21. var commandFactories = container.Resolve<KeyValuePair<CommandId, Func<ICommand>>[]>();
  22. Assert.AreEqual(CommandId.Delete, commandFactories[2].Key);
  23. }
  24. }

解析 KeyValuePair 包装器

使用 KeyValuePair 作为解析对象的包装类型,可获取注册信息的 serviceKey

  • 使用 KeyValuePair 作为包装类型解析的对象时,Key 属性对应的是 serviceKey,而 Value 属性对应的真正解析对象。
  • DryIoc并不能保证返回非 DefaultKey 类型对象的注册顺序,即:对于手动设置 serviceKey 的多个类型之间排序顺序是不能得到保证。

注意:解析集合类型过程中,若多个注册信息使用的 service Key并非是同一类型,那么在 Pair 中需要指定 object 类型作为 TKey。

示例 :通过解析 KeyValuePair 获取 serviceKey

  1. class Resolving_service_with_key_as_KeyValuePair
  2. {
  3. interface I { }
  4. class X : I { }
  5. class Y : I { }
  6. class Z : I { }
  7. [Test]
  8. public void Example()
  9. {
  10. var container = new Container();
  11. container.Register<I, X>();
  12. container.Register<I, Y>();
  13. container.Register<I, Z>(serviceKey: "z");
  14. // 这里将 object 作为 KeyValuePair 的 Tkey
  15. var items = container.Resolve<KeyValuePair<object, I>[]>();
  16. CollectionAssert.AreEqual(
  17. new object[] { DefaultKey.Of(0), DefaultKey.Of(1), "z" },
  18. items.Select(x => x.Key));
  19. // 这里将 DefualtKey 作为 KeyValuePair 的 Tkey
  20. var defaultItems = container.Resolve<KeyValuePair<DefaultKey, I>[]>();
  21. Assert.AreEqual(2, defaultItems.Length);
  22. // 这里将 string 作为 KeyValuePair 的 Tkey
  23. var z = container.Resolve<KeyValuePair<string, I>[]>().Single().Value;
  24. Assert.IsInstanceOf<Z>(z);
  25. }
  26. }

上述例子可以看出,serviceKey 的类型可以起到过滤作用。

注意:DryIoc不保证非默认Key注册类型的解析顺序。因此,在上面的示例中,“z”注册不能保证是最后一个,即使它是最后一个注册的。

IsRegistered 方法

IsRegistered 方法允许你检测某特定类型、装饰器或者包装器是否已在容器中注册。

另外,IsRegistered 方法允许通过提供 condition 去检测注册类型的 Factory。例如,可以检测具体的 Reuse,Metadata 或者 Setup。

示例 :IsRegistered 利用 condition 检测某类型是否以“单例模式”注册

  1. class IsRegistered_examples
  2. {
  3. class MyService { }
  4. [Test]
  5. public void Example()
  6. {
  7. var c = new Container();
  8. // not registered yet
  9. Assert.IsFalse(c.IsRegistered<MyService>(condition: factory => factory.Reuse is SingletonReuse));
  10. c.Register<MyService>();
  11. // Assert通过,此时 MyService 类型已注册
  12. Assert.IsTrue(c.IsRegistered<MyService>());
  13. // Assert通过,这里使用 condition 将 MyService 限定为单例模式作为条件,结果条件不满足
  14. Assert.IsFalse(c.IsRegistered<MyService>(condition: factory => factory.Reuse is SingletonReuse));
  15. c.Register<MyService>(Reuse.Singleton);
  16. // Assert通过,此时 MyService 类型已注册为单例模式
  17. Assert.IsTrue(c.IsRegistered<MyService>(condition: factory => factory.Reuse is SingletonReuse));
  18. }
  19. }

IsRegistered 方法源码:

  • condition 参数类型为 Func,基于 Factory 参数返回 bool 类型用作于过滤条件
  • factoryType 参数 默认为 FactoryType.Service,表明该方法默认情况用于判断“服务类” ```csharp // DryIco源码:src/DryIoc/Container.cs

///

Returns true if is registered in container OR /// its open generic definition is registered in container. /// The additional implementation factory may be specified to narrow the search. public static bool IsRegistered(this IRegistrator registrator, Type serviceType,object serviceKey = null, FactoryType factoryType = FactoryType.Service, Func condition = null) => registrator.IsRegistered(serviceType, serviceKey, factoryType, condition);

  1. IsRegistered 方法支持传入 serviceKey 用于作为查找条件。
  2. <a name="3PY4m"></a>
  3. #### 示例 :IsRegistered 利用 serviceKey 查找指定Key的注册信息
  4. ```csharp
  5. class IsRegistered_with_key_examples
  6. {
  7. class MyService { }
  8. [Test]
  9. public void Example()
  10. {
  11. var c = new Container();
  12. c.Register<MyService>(serviceKey: "the key");
  13. Assert.IsTrue(c.IsRegistered<MyService>(serviceKey: "the key"));
  14. // 注册时提供了字符串作为 sercieKey,因此 DefaultKey.Value 不满足查找条件
  15. Assert.IsFalse(c.IsRegistered<MyService>(serviceKey: DefaultKey.Value));
  16. // 缺少 serviceKey 参数时,会查找所有的注册类型
  17. Assert.IsTrue(c.IsRegistered<MyService>());
  18. c.Register<MyService>();
  19. // 针对未提供 sercieKey的注册信息,可使用 DefaultKey.Value 作为参数
  20. Assert.IsTrue(c.IsRegistered<MyService>(serviceKey: DefaultKey.Value));
  21. }
  22. }

默认情况下,IsRegistered 仅会检测“服务类”,忽略“装饰器”或者“包装器”。通过 factoryType 可以指定查找的目标类型。

  • 手动修改 IsRegister 方法的 factoryType 参数,可用于判断“装饰类”或“包装类”,例如:

    示例 :IsRegistered 利用 factoryType 参数用查找“包装器”

    1. class IsRegistered_for_wrapper_or_decorators
    2. {
    3. class Owned<T> { }
    4. [Test]
    5. public void Example()
    6. {
    7. var c = new Container();
    8. Assert.IsFalse(c.IsRegistered(typeof(Owned<>), factoryType: FactoryType.Wrapper));
    9. c.Register(typeof(Owned<>), setup: Setup.Wrapper);
    10. Assert.IsTrue(c.IsRegistered(typeof(Owned<>), factoryType: FactoryType.Wrapper));
    11. }
    12. }

    重要 :IsRegistered 方法并不会检查“服务类”是否能真的解析。例如:它的某些依赖对象并没有注册。通过 Resolve 方法的 IfUnresolved.ReturnDefault 参数可以解决该问题:

示例 :Resolve 方法使用 IfUnresolved.ReturnDefault 检测是否解析

  1. class Check_if_resolvable
  2. {
  3. class MyService { }
  4. [Test]
  5. public void Example()
  6. {
  7. var c = new Container();
  8. // Assert通过,因未注册MyService类型,此时无法正常解析,根据参数IfUnresolved.ReturnDefault,返回引用类型的默认值(null)
  9. Assert.IsFalse(c.Resolve<MyService>(ifUnresolved: IfUnresolved.ReturnDefault) != null);
  10. c.Register<MyService>();
  11. // Assert通过,已注册MyService类型,此时能正常解析MyService实例
  12. Assert.IsTrue(c.Resolve<MyService>(ifUnresolved: IfUnresolved.ReturnDefault) != null);
  13. // 利用 Func 包装方式,可以在不创建具体实例的情况下检测类型的解析性
  14. // Assert通过,已注册MyService类型,此时能正常解析 Func<MyService> 方法
  15. Assert.IsTrue(c.Resolve<Func<MyService>>(ifUnresolved: IfUnresolved.ReturnDefault) != null);
  16. }
  17. }

以隐式方式获知“服务类”是否已注册

GetSercieRegistrations 方法用于获取容器中所有的服务类注册信息。

示例 :使用 GetSercieRegistrations 方法获取所有服务类注册信息

  1. class Get_specific_registration
  2. {
  3. class MyService { }
  4. [Test]
  5. public void Example()
  6. {
  7. var c = new Container();
  8. c.Register<MyService>(Reuse.Scoped, serviceKey: "foo");
  9. // 这里通过 GetSericeRegistration 方法获取所有的注册信息
  10. var serviceRegistration = c.GetServiceRegistrations()
  11. .FirstOrDefault(r => Equals(r.OptionalServiceKey, "foo") && r.Factory.Reuse == Reuse.Scoped);
  12. Assert.AreEqual(typeof(MyService), serviceRegistration.ImplementationType);
  13. }
  14. }

RegisterMany 方法

Batch registering the implementations with possibly many service types,throwing the “Error.NoServicesWereRegisteredByRegisterMany” error when there are no services types to register.

RegisterMany 方法允许批量注册。此外,它会自动从“实现类”(或者程序集中实现类)推论出“服务类”。

使用 RegisterMany 方法可同时为多个类型实现注册

示例 :使用 RegisterMany 方法注册多个类型

  1. public interface X { }
  2. public interface Y { }
  3. public class A : X, Y { }
  4. public class B : X, IDisposable
  5. {
  6. public void Dispose() { }
  7. }
  8. public static A CreateA() => new A();
  9. // 利用 rules 参数设置 WithTrackingDisposableTransients,启用瞬时对象跟踪功能
  10. var container = new Container(rules => rules.WithTrackingDisposableTransients());
  • 注册单个“实现类” ```csharp // 为 X,Y以及A本身, 同时注册“实现类” A container.RegisterMany();

// 使用 serviceTypeConditon 参数,设置过滤条件:只为接口(X,Y)注册“实现类”A container.RegisterMany(serviceTypeCondition: type => type.IsInterface);

// 使用 reuse 参数,设置为单例模式 container.RegisterMany(Reuse.Singleton); Assert.AreSame(container.Resolve(), container.Resolve());

  1. - 同时注册多个“实现类”
  2. ```csharp
  3. // 同时注册 A 与 B,利用serviceTypeCondition参数,设置过滤条件:只为接口类型注册,即 X、Y 注册 A,X 注册 B
  4. // 此时 Resolve<X>() 对象会抛出错误,因为 X 同时注册了 A 与 B
  5. container.RegisterMany(new[] { typeof(A), typeof(B) },serviceTypeCondition: type => type.IsInterface);
  6. // 同时注册 A 与 B,利用serviceTypeCondition参数,设置过滤条件:只为 X 注册 A 与 B
  7. // 此时 Resolve<X>() 对象会抛出错误,因为 X 同时注册了 A 与 B
  8. container.RegisterMany(new[] { typeof(A), typeof(B) },serviceTypeCondition: type => type == typeof(X));
  9. // 注册 A 所在程序集中的其他类型,利用serviceTypeCondition参数,设置过滤条件:只为 X 注册 A 与 B
  10. container.RegisterMany(new[] { typeof(A).Assembly }, type => type == typeof(X));

// DryIco源码:src/DryIoc/Container.cs

public class Made { public static TypedMade Of(Expression> serviceReturningExpr, params Func[] argValues); }

  1. - “显式”注册
  2. ```csharp
  3. // 为 X,Y 注册 A
  4. container.RegisterMany(new[] { typeof(X), typeof(Y) }, typeof(A));
  5. // 抛出异常:A 并未注册为“服务类”
  6. container.Resolve<A>();
  • 自定义注册参数
    1. container.RegisterMany(new[] { typeof(A).Assembly },
    2. getServiceTypes: implType => implType.GetImplementedServiceTypes(),
    3. getImplFactory: implType => new ReflectionFactory(implType,
    4. reuse: implType.IsAssignableTo<IDisposable>() ? Reuse.Scoped : Reuse.Transient,
    5. made: FactoryMethod.ConstructorWithResolvableArguments));

DryIoc 不会将某些类型视为 RegisterMany 方法的服务类型。这些类型包括 .Net基元类型、object、string以及某些通常接口(例如:IDisposable,ICloneable)。编译器生成的类型同样排除在外。

关于Registrator.ExcludedGeneralPurposeServiceTypes

  • 通过 Registrator.ExcludedGeneralPurposeServiceTypes 属性获取当前框架下 RegisterMany 方法不支持的 Type 集合
  • 针对 RegisterMany 不支持的 Type,可以使用 Register 方法。
    1. var excludedTypes = Registrator.ExcludedGeneralPurposeServiceTypes;

RegisterMapping 方法

Registers new service type with factory for registered service type.

RegisterMapping 方法允许为已存在注册信息新增一个新注册。

示例 :RegisterMapping 方法基本使用

  1. class Register_mapping
  2. {
  3. public interface I { }
  4. public interface J { }
  5. class S : I, J { } // implements both I and J
  6. [Test]
  7. public void Example()
  8. {
  9. var container = new Container();
  10. // 为 I 注册 S (单例模式)
  11. container.Register<I, S>(Reuse.Singleton);
  12. // 为 J 注册匹配 I,即相当于为 J 注册 S (单例)
  13. container.RegisterMapping<J, I>();
  14. Assert.AreSame(container.Resolve<I>(), container.Resolve<J>());
  15. }
  16. }

示例 :RegisterMany 方法实现 RegisterMapping 方法的效果

  1. class Register_mapping_with_RegisterMany
  2. {
  3. public interface I { }
  4. public interface J { }
  5. class S : I, J { } // implements both I and J
  6. [Test]
  7. public void Example()
  8. {
  9. var container = new Container();
  10. container.RegisterMany(new[] { typeof(I), typeof(J) }, typeof(S), Reuse.Singleton);
  11. Assert.AreSame(container.Resolve<I>(), container.Resolve<J>());
  12. Assert.AreSame(container.Resolve<I>(), container.Resolve<J>());
  13. }
  14. }