如何从IoC容器中解析类型集合

时间:2014-04-25 23:06:29

标签: ioc-container mvvmcross

我们在我们的应用中使用MvvmCross,并使用MvxSimpleIoCContainer

在应用启动时,我们会注册所有迁移 这很容易,因为所有迁移都是从IMigration

继承的
typeof (IMigration)
    .Assembly
    .CreatableTypes()
    .Inherits<IMigration>()
    .AsTypes()
    .RegisterAsLazySingleton();

注册迁移后,我们需要连续运行它们,因此MigrationRunner看起来像这样。

Mvx.Resolve<IMigrationRunner>().RunAll(SystemRole.Client, new List<IMigration>
    {
        Mvx.IocConstruct<Migration001>(),
        Mvx.IocConstruct<Migration002>()
    });

正如您所看到的,我明确地使用Mvx构建每个迁移。当一堆迁移最终在应用程序中时,这变得乏味并且容易出错。

我希望能够做的就是一举解决整个集合,而不是每次创建新的迁移时都不需要触摸它。

有没有办法通过MvvmCross来做到这一点?


伪代码

Mvx.Resolve<IMigrationRunner>()
   .RunAll(SystemRole.Client, Mvx.ResolveAll<IMigration>());

2 个答案:

答案 0 :(得分:2)

我会使用LINQ来获取类型列表。遗憾的是,无法获得已注册类型的列表,因此您必须再次枚举类型,就像注册时一样。您甚至可以按类型名称排序。现在您有了一个类型列表,您可以创建一个新的实例化/已解析类型列表以传递给RunAll()。类似的东西:

var migrationTypes = typeof (IMigration)
    .Assembly
    .CreatableTypes()
    .Inherits<IMigration>()
    .AsTypes()
    .OrderBy(t => t.Name)
    .ToList();

Mvx.Resolve<IMigrationRunner>()
    .RunAll(SystemRole.Client,
         migrationTypes.Select(t => Mvx.Resolve(t)).ToList());

这是“浏览器”代码,所以没有保证,但你得到了要点。

答案 1 :(得分:1)

好的,所以现在反思是这个问题的答案,最后,我想扩展我们的自定义MvxServiceLocator : IServiceLocator以包含类似

的内容

public IEnumerable<object> GetAllInstances(Type serviceType){...}

但是现在我在应用中只获得了RunMigrations()方法

private void RunMigrations()
{
    var migrationType = typeof (IMigration); // IMigration is in a separate assembly
    var migrations = GetType().Assembly
                              .GetTypes()
                              .Where(
                                  t => migrationType.IsAssignableFrom(t) && !t.IsAbstract)
                              .OrderBy(t => t.Name)
                              .Select(m => _serviceLocator.GetInstance(m) as IMigration)
                              .ToList();

    var migrationRunner = new MigrationRunner(Mvx.Resolve<IDbProvider>());
    migrationRunner.RunAll(SystemRole.Client, migrations);
}

其中_serviceLocator.GetInstance(m)只存在于我们的自定义MvxServiceLocator

public object GetInstance(Type serviceType)
{
    return _ioCProvider.Resolve(serviceType);
}

编辑:这是我如何扩展我们的服务定位器包装器。

public class MvxServiceLocator : IServiceLocator
{
    private readonly IMvxIoCProvider _ioCProvider;

    public MvxServiceLocator(IMvxIoCProvider ioCProvider)
    {
        _ioCProvider = ioCProvider;
    }

    public IEnumerable<TService> GetAllInstances<TService>()
    {
        var serviceType = typeof(TService);
        var registrations = GetType().Assembly
                                     .GetTypes()
                                     .Where(
                                         t => serviceType.IsAssignableFrom(t) && !t.IsAbstract)
                                     .Select(m => (TService)_ioCProvider.Resolve(m));
        return registrations;
    }
}