4

現在、caliburn.micro について詳しく学んでいますが、すばらしいです。

いくつかのナビゲーションを備えた私の小さなデモ プロジェクトには、MEF と EventAggregator があります。

Unityが既に使われているプロジェクトでcaliburn.microを使いたいので、UnityをDIに使いたいです。

Unity を使用するようにブートストラップを設定するにはどうすればよいですか?

MindScape チュートリアルと codeplex ページにあるもの以外の優れたチュートリアルは大歓迎です。(ただし、このケースを適切に処理しているものは見当たりませんでした)

4

2 に答える 2

9

CMのWiki は非常に役に立ち、Unity/CSL のバックグラウンドがあるため、Bootstrapper<TRootModel>メソッド名とシグネチャは直感的でした。

Unity 3 を利用する独自のクラスを共有したいと思いましたUnityBootstrapper<TRootModel>。それは小さく、クリーンで、期待どおりの動作をします。

/// <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;
    }
}

これを直接インスタンス化して、有効なジェネリック型パラメーターを提供するか、Lifetime Manager などをサブクラス化してカスタマイズできます。

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();
    }
}
于 2013-06-29T07:05:16.257 に答える
8

IoC コンテナーを接続するためにブートストラップでオーバーライドする必要がある 4 つのメソッドがあります (を使用する場合Boostrapper<T>)。

  1. Configure()

    通常、ここでコンテナを初期化し、すべての依存関係を登録します。

  2. GetInstance(string, Type)

    タイプとキーによるオブジェクトの取得-私が知る限り、通常、ビューモデル、通常の依存関係などを取得するためにフレームワークによって使用されます。したがって、ここでは、コンテナーはandstring /orに基づいてインスタンスを取得する必要があります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.
    }
}
于 2013-03-31T19:51:15.207 に答える