2016-06-14 14 views
15

私はUnityの依存性注入について読んできました。私はそれが物事であり、インターフェイスにクラスを入力できることを理解しています。私が好奇心を持っているのは、私がしなければならないことですか?以下のシナリオでは、同じスペースにTerrainGeneratorTileCreatorがあります。どのようにして発電機内のTileCreatorを依存関係にすることができますか? C#の依存関係を自動的に解決するにはどうすればよいですか?

enter image description here

http://geekswithblogs.net/danielggarcia/archive/2014/01/23/introduction-to-dependency-injection-with-unity.aspx

はタイプを登録を通じて、私を歩くが、私はそれを注入限りクラスはユニティ資産セクションに表示されているとして、それが自動的にできるようになりますことをどこかで読ん、私は理解できません可能であれば、構文を外してください。

更新

私はかなりいらいらすることができ、大規模なシステムで...単一ファイル内のすべてのクラスを置くことができます。その間に、私は試してみるアプローチです。それはまったく動作しないよりも優れています。 Unityは、クラスを見てコンストラクタと、自動的にこれらの解像度を実行し、私のクラスでそれらを注入コンストラクタすることができるはずのよう

更新 は思えます。それは可能ですか?

+3

がよろしいです[タグ:unity3d]依存性の注入を持っていますか?マイクロソフトで同様の名前の[タグ:団体]について読んでいないと確信していますか?リンク先のリンクはUnity TechnologiesのUnityではなく、[MicrosoftのUnity](https://msdn.microsoft.com/en-us/library/ff647202.aspx)です。あなたが達成しようとしていることははっきりとは分かりません。何をしようとしているのかをもっと説明できますか? –

+0

私はUnity3dについて間違いなく尋ねています。私はそれらが2つの異なるものであることを認識しませんでした。それを指摘してくれてありがとう。 – Webnet

+2

'MonoBehavior'クラスのコンストラクタには触れないでください。あなたの質問は、依然として依存性注入の作業に集中しています。なぜなら、***なぜあなたが依存性注入を最初に働かせる必要があるのか​​**について説明していないからです。これは[XY問題](http:// meta.stackexchange.com/questions/66377/what-is-the-xy-problem)、あなたの質問を再編集し、あなたが持っているリアルな問題についての詳細を追加してください(*「TerrainGeneratorとTileCreatorが同じスペースにある」*)。人々はそれを手助けすることができます... –

答えて

8

あなたはUnity3dエンジンのDIを探しているなら、多分これが働くだろう(私はそれを使用していませんでしたが、フィードバックが正)https://github.com/modesttree/Zenject

あなたは、MicrosoftのユニティDIライブラリについて話している場合は、あなたがすべきこれを行うことができます:

container.RegisterTypes(
    AllClasses.FromLoadedAssemblies(), 
    WithMappings.FromMatchingInterface, 
    WithName.Default); 
+0

ビンゴ、それは私が探していたものです。このようなクリーンなソリューションを強調していただきありがとうございます。私はまだそれがクラスのコンストラクタを見て、そのクラスの依存関係を自動的に構築するほどスマートだったら – Webnet

4

私は常に次のコードを使用します。アプリケーションをロードすると、アプリケーションはディレクトリ内ですべてのDLLを探します。このようにして、リフレクションを使用してクラスをロードすると、Dllとexesが検索されます。検索にいくつかのパスを追加することもできます。

AppDomain currentDomain = AppDomain.CurrentDomain; 
currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve); 

Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     string defaultFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 

     string assemblyName = new AssemblyName(args.Name).Name; 

     string assemblyNameDll = assemblyName + ".dll"; 
     string assemblyNameExe = assemblyName + ".exe"; 

     string assemblyPathDll = Path.Combine(defaultFolder, assemblyNameDll); 
     string assemblyPathExe = Path.Combine(defaultFolder, assemblyNameExe); 

     string assemblyPathToUse = null; 
     if (File.Exists(assemblyPathDll)) 
     { 
      assemblyPathToUse = assemblyPathExe; 
     } 
     else if (File.Exists(assemblyPathExe)) 
     { 
      assemblyPathToUse = assemblyPathExe; 
     } 
     else 
     { 
      IEnumerable<string> merge = AssemblyFolders.Values; 
      if (!string.IsNullOrEmpty(TempLoadingFolder)) 
      { 
       merge = AssemblyFolders.Values.Union(new List<string>() { TempLoadingFolder }); 
      } 
      foreach (var folder in merge) 
      { 
       assemblyPathDll = Path.Combine(folder, assemblyNameDll); 
       assemblyPathExe = Path.Combine(folder, assemblyNameExe); 

       if (File.Exists(assemblyPathDll)) 
       { 
        assemblyPathToUse = assemblyPathDll; 
        break; 
       } 
       else if (File.Exists(assemblyPathExe)) 
       { 
        assemblyPathToUse = assemblyPathExe; 
        break; 
       } 
      } 
     } 

     Assembly assembly = null; 

     if (assemblyPathToUse != null && File.Exists(assemblyPathToUse)) 
     { 
      assembly = Assembly.LoadFrom(assemblyPathToUse); 
     } 
     return assembly; 
    } 
1

いいえ、インターフェイスを使用する必要はありません。具体的なタイプも登録して解決できます。次のように

たとえば、あなたはTerrainGeneratorTileCreatorを登録することができます。

var myTileCreator = new TileCreator(); 
container.RegisterType<TerrainGenerator>(new PerThreadLifetimeManager(), new InjectionFactory(c => new TerrainGenerator(myTileCreator))); 

TerrainGeneratorを解決するには:

TerrainGenerator generator = container.Resolve<TerrainGenerator>(); 

が異なるTerrainGeneratorを解決するにはTileCreator

TerrainGenerator generator = container.Resolve<TerrainGenerator>(new ParameterOverride("tileCreator", new TileCreator())); 

あなたは、プロパティ注射と同様のような多くの有用な情報のためのDependency Injection with Unity - Patterns and Practicesを読むことをお勧めします。

希望に役立ちます。

1

クラスが同じファイルにあるかどうかは関係ありません。 Unityは、型を指定してインスタンスを作成する方法を知る必要があります。

RegisterInstanceを使用すると、型としてResolveが呼び出されるたびに、引数として渡される特定のオブジェクトが返されます。タイプがRegisterTypeを使用して登録されている(または具体的なクラスに登録されていない)場合、Unityは最も多くの引数を持つコンストラクタを使用して型のインスタンス化を試みます。それぞれのパラメータタイプに対して、Unityはそれらを再帰的に解決しようとします。

インターフェイスタイプの具体的な型へのマッピングの登録は必須ですが、具体的な型自体の登録はオプションです。

サンプルコード:

using Microsoft.Practices.Unity; 
using System; 

namespace Unity 
{ 
    interface IFooBar 
    { 
     string Message(); 
    } 

    class Foo 
    { 
     string msg; 

     public Foo() 
     { 
      msg = "Hello"; 
     } 

     public override string ToString() 
     { 
      return msg; 
     } 
    } 

    class Bar 
    { 
     private Foo _f; 
     private IFooBar _fb; 
     public Bar(Foo f, IFooBar fb) 
     { 
      this._f = f; 
      this._fb = fb; 
     } 

     public override string ToString() 
     { 
      return _f.ToString() + " World " + _fb.Message(); 
     } 
    } 

    class FooBar : IFooBar 
    { 
     public string Message() 
     { 
      return "Unity!"; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      UnityContainer container = new UnityContainer(); 
      container.RegisterType<IFooBar, FooBar>(); // required 
      container.RegisterType<Foo>(); // optional 
      container.RegisterType<Bar>(); // optional 

      var mybar = container.Resolve<Bar>(); 

      Console.WriteLine(mybar); 
     } 
    } 
} 

https://msdn.microsoft.com/en-us/library/microsoft.practices.unity.iunitycontainer_methods(v=pandp.20).aspx

関連する問題