[Attribute,Spring,构造函数,Autowired,Identifier]在netcore中如何注入同一个接口的多个实现

  netcore中自带了Ioc框架,这也影响了我们的编码习惯,以前都是静态类或者直接new对象,现在有了Ioc框架的支持,我们也不必守旧,应当使用起来,接受这种对象管理方式。使用过java的同仁,都习惯了Spring,感觉离开了Spring就好像失去了灵魂一样。Spring经过多年的沉淀,非常的稳定和灵活,相比之下,netcore中自带的Ioc框架太过轻量,中规中矩的使用还算够用,但是其灵活性的确有待加强。比如属性注入、字段注入、方法参数注入等等,虽然说官方强烈建议使用构造函数注入,并且只提供了构造函数注入,但是我感觉后期肯定会支持更多都注入方法的,并且会结合Attribute提供更为灵活的功能,期望这一天能快点到来!

  今天主要讨论其中一个问题,就是如何在netcore中注入同一个接口的多个实现,注册多个实现并不难,关键是如何优雅的取出来。下面我们用代码来说话:

  public interface IServiceA

  {

  string GetStr();

  }

  public class ImplA1 : IServiceA

  {

  public string GetStr()

  {

  return "ImplA1";

  }

  }

  public class ImplA2 : IServiceA

  {

  public string GetStr()

  {

  return "ImplA2";

  }

  }

  上面的代码是有一个服务接口IServieA,和两个不同的实现类。如果我们这样注册:

  services.AddSingleton(new ImplA1());

  services.AddSingleton(new ImplA2());

  第一种使用方式:

  public class HomeController : Controller

  {

  private readonly IServiceA serviceA;

  public HomeController(IServiceA serviceA)

  {

  this.serviceA=serviceA; //这里注入进来的是最后一个实现,也就是ImplA2

  }

  public IActionResult Index()

  {

  return Content(serviceA.GetStr());

  }

  }

  这种方法肯定是不行的,因为只能获取注册的最后一个实现。

  第二种使用方式:

  public class HomeController : Controller

  {

  private readonly IServiceA serviceA;

  public HomeController(IEnumerable serviceAList)

  {

  this.serviceA=serviceAList.First(); //这里注入进来的是一个QQ转让平台非要服务集合

  }

  public IActionResult Index()

  {

  return Content(serviceA.GetStr());

  }

  }

  这种方法也不好,需要自己在集合中筛选要想的实现。

  其实我们更希望是这样的,注册的时候可以使用一个标识,然后使用Attribute指定标识来获取具体的实现:

  services.AddSingleton("impla1",new ImplA1()); //impla1为该实现在该接口的唯一标识

  services.AddSingleton("impla2",new ImplA2()); //同上

  可能会有这么一个Attribute类:

  public class IdentifierAttribute : Attribute

  {

  public IdentifierAttribute(string id)

  {

  this.Id=id;

  }

  public string Id { get; set; }

  }

  然后使用的时候大概是这样:

  public HomeController([Identifier("impla1")]IServiceA serviceA)

  {

  this.serviceA=serviceA; //根据Identifier的指定,这里应该是ImplA1,

  }

  如果能像Spring中@Autowired注解,注入字段就更好了:

  [Autowired]

  [Identifier("impla1")]

  private readonly IServiceA serviceA;

  然而,我们该醒醒了,netcore中自带的Ioc没有提供类似这样的功能,我找了很久也没找到。

  作为程序员,我们都要具备一种特质,那就是爱思考,经过思考,我感觉可以使用工厂来解决这个问题。这里只是提供一种思路和实现,有更好的方法大家可以留言讨论。

  首先我们定义一个用于存储单例的集合类:

  public class SingletonFactory

  {

  Dictionary> serviceDict;

  public SingletonFactory()

  {

  serviceDict=new Dictionary>();

  }

  public TService GetService(string id) where TService : class

  {

  var serviceType=typeof(TService);

  return GetService(serviceType, id);

  }

  public TService GetService(Type serviceType, string id) where TService : class

  {

  if (serviceDict.TryGetValue(serviceType, out Dictionary implDict))

  {

  if (implDict.TryGetValue(id, out object service))

  {

  return service as TService;

  }

  }

  return null;

  }

  public void AddService(TService service, string id) where TService : class

  {

  AddService(typeof(TService), service, id);

  }

  public void AddService(Type serviceType, object service, string id)

  {

  if (service !=null)

  {

  if (serviceDict.TryGetValue(serviceType, out Dictionary implDict))

  {

  implDict[id]=service;

  }

  else

  {

  implDict=new Dictionary();

  implDict[id]=service;

  serviceDict[serviceType]=implDict;

  }

  }

  }

  }

  这个类中使用一个嵌套的字典来存储服务类的实现,提供添加服务和获取服务的方法。

  有了这样一个类,在netcore自带的Ioc中我们就可以获取更多的控制权了。且看下面代码。

  注册服务:

  SingletonFactory singletonFactory=new SingletonFactory();

  singletonFactory.AddService(new ImplA1(), "impla1");

  singletonFactory.AddService(new ImplA2(), "impla2");

  services.AddSingleton(singletonFactory);

  我们把同一个接口的多个实现都加到SingletonFactory中,然后把SingletonFactory注册到Ioc。

  使用服务:

  private readonly IServiceA serviceA;

  public HomeController(SingletonFactory singletonFactory)

  {

  this.serviceA=singletonFactory.GetService("impla2"); //使用标识从SingletonFactory获取自己想要的服务实现

  }

  使用服务都时候我们注入SingletonFactory,然后从SingletonFactory根据标识获取具体的服务实现。

  这个方法还算优雅吗?,目前来看我是可以接受了,不过还是希望官方能早些提供更强大更灵活的功能,期待netcore会越来越好!

  

在netcore中如何注入同一个接口的多个实现

おすすめ

転載: blog.csdn.net/iqifenxia/article/details/121788728