Caliburn.micro与Unity

4
目前我正在学习caliburn.micro,它非常棒。
在我的小演示项目中有一些导航,其中包含MEF和EventAggregator。
由于我想在一个已经使用Unity的项目中使用caliburn.micro,所以我想使用Unity进行DI。
如何设置引导程序来使用Unity?
除了MindScape教程和CodePlex页面上的教程之外,任何好的教程都非常受欢迎。(除了我没有看到适合这种情况的正确教程)
2个回答

9
我发现 CM维基非常有帮助,作为Unity/CSL背景下的人,Bootstrapper<TRootModel>方法名和签名很直观。
我想分享我的类UnityBootstrapper<TRootModel>,它利用Unity 3,代码简洁小巧,功能符合预期。
/// <summary>
/// <para>Unity Bootstrapper for Caliburn.Micro</para>
/// <para>You can subclass this just as you would Caliburn's Bootstrapper</para>
/// <para>http://caliburnmicro.codeplex.com/wikipage?title=Customizing%20The%20Bootstrapper</para>
/// </summary>
/// <typeparam name="TRootModel">Root ViewModel</typeparam>
public class UnityBootstrapper<TRootModel>
    : Bootstrapper<TRootModel>
    where TRootModel : class, new()
{
    protected UnityContainer Container
    {
        get { return _container; }
        set { _container = value; }
    }

    private UnityContainer _container = new UnityContainer();

    protected override void Configure()
    {
        if (!Container.IsRegistered<IWindowManager>())
        {
            Container.RegisterInstance<IWindowManager>(new WindowManager());
        }
        if (!Container.IsRegistered<IEventAggregator>())
        {
            Container.RegisterInstance<IEventAggregator>(new EventAggregator());
        }
        base.Configure();
    }

    protected override void BuildUp(object instance)
    {
        instance = Container.BuildUp(instance);
        base.BuildUp(instance);
    }

    protected override IEnumerable<object> GetAllInstances(Type type)
    {
        return Container.ResolveAll(type);
    }

    protected override object GetInstance(Type type, string name)
    {
        var result = default(object);
        if (name != null)
        {
            result = Container.Resolve(type, name);
        }
        else
        {
            result = Container.Resolve(type);
        }
        return result;
    }
}

你可以直接实例化它,提供有效的泛型类型参数,或者你可以子类化并自定义一些东西,例如生命周期管理器:
public class AppBootstrapper
    : UnityBootstrapper<ViewModels.AppViewModel>
{
    protected override void Configure()
    {
        // register a 'singleton' instance of the app view model
        base.Container.RegisterInstance(
            new ViewModels.AppViewModel(), 
            new ContainerControlledLifetimeManager());

        // finish configuring for Caliburn
        base.Configure();
    }
}

8

在使用 Boostrapper<T> 时,有4个方法需要重写以连接IoC容器:

  1. Configure()

    通常在这里初始化容器并注册所有依赖项。

  2. GetInstance(string, Type)

    按类型和关键字检索对象 - 据我所知,通常由框架用于检索例如视图模型、常规依赖项等。因此,在这里你的容器必须以某种方式基于 string 和/或 Type(通常是类型;当你使用视图优先绑定将模型绑定到视图时,会使用字符串)获取实例。通常容器内置了类似的方法,可以直接使用或稍加调整。

  3. GetAllInstances(Type)

    检索对象集合(仅按类型) - 同样据我从经验中了解,Caliburn.Micro用于视图。

  4. BuildUp(object)

    一个方法,在这里你可以对一个对象进行属性注入。

如果您感兴趣,我有一个使用 SimpleInjector(或 Autofac)的示例,不幸的是我没有 Unity 的经验。

[编辑]

示例时间!这个示例使用 SimpleInjector。

public class MainViewModel
{
//...
}

public class ApplicationBootstrapper : Bootstrapper<MainViewModel>
{
    private Container container;

    protected override void Configure()
    {
        container = new Container();

        container.Register<IWindowManager, WindowManager>();
      //for Unity, that would probably be something like:
      //container.RegisterType<IWindowManager, WindowManager>();
        container.RegisterSingle<IEventAggregator, EventAggregator>();

        container.Verify();
    }

    protected override object GetInstance(string key, Type service)
    {
        // Now, for example, you can't resolve dependency by key in SimpleInjector, so you have to
        // create the type out of the string (if the 'service' parameter is missing)
        var serviceType = service;
        if(serviceType == null)
        {
            var typeName = Assembly.GetExecutingAssembly().DefinedTypes.Where(x => x.Name == key).Select(x => x.FullName).FirstOrDefault();
            if(typeName == null)
                throw new InvalidOperationException("No matching type found");

            serviceType = Type.GetType(typeName);
        }

        return container.GetInstance(serviceType);
        //Unity: container.Resolve(serviceType) or Resolve(serviceType, name)...?

    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return container.GetAllInstances(service);
        //Unity: No idea here.
    }

    protected override void BuildUp(object instance)
    {
        container.InjectProperties(instance);
        //Unity: No idea here.
    }
}

是的,任何样品都可以,因为我知道Unity,我可能可以看到我需要改变的东西。 - Mare Infinitus
非常感谢。我需要看看是否真的需要GetAllInstances和BuildUp,或者一个空实现就足够了。我绝对不使用属性注入。也许Caliburn在某个地方需要它。 - Mare Infinitus
@MareInfinitus 我认为GetAllInstances是必要的来解析视图,但是BuildUp似乎只是可选的,仅用于属性注入。但我会再次确认一下。 - Patryk Ćwiek
认为这是可以实现的。稍后必须尝试一下。非常感谢! - Mare Infinitus
5
Unity API中的方法与这些方法有一一对应之关系 - GetInstance(Type, string) -> container.Resolve(Type, string),GetAllInstances(Type) -> container.ResolveAll(Type),BuildUp(object) -> container.BuildUp(object, instance.GetType())。实现启动程序应该很容易。 - Chris Tavares
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接