Caliburn Micro 获取服务实例

Caliburn Micro get service instance

我正在为 WinRT 应用程序使用 Caliburn Micro。我已经在我的 App.xaml.cs 中注册了一项服务,请参阅下面的示例代码

public sealed partial class App
    {
        private WinRTContainer _container;

      public App()
        {
            InitializeComponent();
            Resuming += AppResuming;
        }

        protected override void Configure()
        {
            _container = new WinRTContainer();

            _container.RegisterWinRTServices();

            _container.Singleton<ISampleService, SampleService>();
            //some more viewmodels & services added
        }

protected override void PrepareViewFirst(Frame rootFrame)
        {
            _container.RegisterNavigationService(rootFrame);
        }

protected override object GetInstance(Type service, string key)
        {
            return _container.GetInstance(service, key);
        }

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return _container.GetAllInstances(service);
        }

        protected override void BuildUp(object instance)
        {
            _container.BuildUp(instance);
        }
}

现在,我有一个实用程序 class,我想在其中获取此 SampleService 的实例。

如何获取实例?

我假设您将 MEF 与 Caliburn.Micro

一起使用

所以你可以通过这种方式获得一个实例:

SampleService service = IoC.Get<ISampleService>();

希望对您有所帮助。

Guerudo 的答案有效,但除非万不得已,否则切勿使用 IoC.Get<>。使用服务定位器被认为是一种反模式。

获取实例的正确时机是使用构造函数注入。假设您有一个 MainViewModel,执行此操作

public class MainViewModel
{
    private readonly ISampleService _sampleService;

    public MainViewModel(ISampleService sampleService)
    {
        _sampleService = sampleService   
    }

}

并在您的 ViewModel 中的任何位置使用 _sampleService。

而且 Caliburn.Micro 不需要任何 MEF 属性。

在大多数情况下,您应该避免直接从容器中取出东西。相反,请考虑使用依赖注入。

例如,如果你想在SomeUtility class中使用ISampleService,这是从SomeViewModel调用的,那么首先你需要注册所有三种类型在容器中。

public class AppBootstrapper : BootstrapperBase
{
    protected override void Configure()
    {
        ...

        _container.Singleton<ISampleService, SampleService>();
        _container.Singleton<SomeUtility>();
        _container.PerRequest<SomeViewModel>();
    }
}

现在,由于 SomeUtility 依赖于 ISampleService,您应该创建 SomeUtility 构造函数,它将接受 ISampleService.

class SomeUtility
{
    private ISampleService _service;

    public SomeUtility(ISampleService service)
    {
        _service = service;
    }
}

如果 SomeViewModel 将使用 SomeUtility,则也应将适当的构造函数添加到 SomeViewModel

class SomeViewModel : Caliburn.Micro.Screen
{
    private SomeUtility _utility;

    public SomeViewModel(SomeUtility utility)
    {
        _utility = utility;
    }
}

最后,让我们将 SomeViewModel 添加到 ShellViewModel 构造函数中。

class ShellViewModel : PropertyChangedBase, IShell
{
    private SomeViewModel _vm;

    public ShellViewModel(SomeViewModel vm)
    {
        _vm = vm;
    }
}

就是这样! ShellViewModel 将获得 SomeViewModel 个实例,SomeViewModel 将获得 SomeUtilitySomeUtility 将获得您的 ISampleService。而这一切都将由容器来解决,所以你不需要手动创建new SomeUtility();或者从容器中拉取IoC.Get<ISampleService>();.

另外您可能想知道:如果 SomeViewModel 应该根据请求创建,例如,当用户单击 "Add" 按钮时会怎样?好吧,我很高兴你问了。 :) 对于这种情况,您可以使用工厂方法!

注册容器即可。

public class AppBootstrapper : BootstrapperBase
{
    protected override void Configure()
    {
        ...

        _container.Handler<IScreen>((x) => x.GetInstance<SomeViewModel>());
    }
}

现在您可以轻松地将它注入到构造函数中,并使用它根据需要创建任意数量的 SomeViewModel 实例。

class ShellViewModel : Conductor<IScreen>.Collection.AllActive, IShell
{
    private Func<SomeViewModel> _vmFactory;

    public ShellViewModel(Func<SomeViewModel> vmFactory)
    {
        _vmFactory = vmFactory;
    }

    public void Add()
    {
        var newVM = _vmFactory();
        ActivateItem(newVM);
    }
}