2016-06-14 22 views
15

Ho letto dell'iniezione di dipendenza di Unity e ho capito che è una cosa e che consente di digitare una classe in un'interfaccia. Quello che mi interessa è, DEVO? Nello scenario sottostante c'è uno TerrainGenerator e TileCreator nello stesso spazio. Come posso ottenere il TileCreator all'interno del generatore come dipendenza?Come posso risolvere automaticamente le dipendenze C#?

enter image description here

http://geekswithblogs.net/danielggarcia/archive/2014/01/23/introduction-to-dependency-injection-with-unity.aspx mi passeggiate attraverso la registrazione di un tipo, ma ho letto da qualche parte che fino a quando la classe è visibile nella sezione Assets Unity sarà in grado di auto iniettare, io proprio non riesco a capire fuori la sintassi (se è possibile).

Aggiornamento

ho potuto mettere tutte le classi in un unico file ... con un grande sistema che potrebbe essere piuttosto fastidioso. Nel frattempo è un approccio che proverò - meglio che non farlo funzionare affatto.

aggiornamento Sembra come unità dovrebbe essere in grado di guardare una classe di costruttore e di eseguire automaticamente queste risoluzioni e li inietta nella mia classe costruttore. È possibile?

+3

Sei sicuro [tag: Unity3D] ha Dependency Injection? Sei sicuro di non aver letto sul nome simile [tag: unity] di Microsoft? Il link a cui si è collegati sta parlando di [Microsoft's Unity] (https://msdn.microsoft.com/en-us/library/ff647202.aspx), non dell'unità Unity Technologies. Non è esattamente chiaro cosa stai cercando di ottenere, puoi spiegare di più quello che stai cercando di fare? –

+0

Sto sicuramente chiedendo di Unity3d, non mi ero reso conto che erano due cose diverse. Grazie per la segnalazione. – Webnet

+2

Non si dovrebbe mai toccare il costruttore di una classe 'MonoBehavior'. La tua domanda è troppo focalizzata su come far funzionare l'iniezione di dipendenza e non hai spiegato abbastanza su *** perché devi far funzionare l'iniezione di dipendenza in primo luogo ***, questo è noto come [XY Problem] (http: // meta.stackexchange.com/questions/66377/what-is-the-xy-problem), rielaborate la vostra domanda e aggiungete ulteriori dettagli sul vero problema che avete (* "c'è un TerrainGenerator e TileCreator nello stesso spazio" *) e le persone saranno in grado di aiutarti con questo ... –

risposta

8

Se siete alla ricerca di DI per il motore Unity3d, forse questo dovrebbe funzionare (io non ho usato, ma il feedback è positivo) https://github.com/modesttree/Zenject

Se si sta parlando di biblioteca Unità DI di Microsoft, si dovrebbe essere in grado di fare questo:

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

Bingo, questo è quello che stavo cercando. Grazie per aver evidenziato una soluzione così pulita. Continuo a desiderare che fosse abbastanza intelligente da guardare un costruttore di classi e costruire automaticamente le dipendenze di quella classe – Webnet

4

Io uso sempre il seguente codice. Quando carico un'applicazione, l'applicazione cerca nella directory tutte le DLL. In questo modo quando si carica una classe con la riflessione, si cercano le Dll e gli ex. Puoi anche aggiungere altri percorsi alla ricerca.

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

No, non è necessario utilizzare le interfacce, è possibile registrare e risolvere anche i tipi di calcestruzzo.

Ad esempio, è possibile registrare il TerrainGenerator e TileCreator come segue:

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

Per risolvere TerrainGenerator:

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

Per risolvere TerrainGenerator con un diverso TileCreator:

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

Si consiglia di leggere Dependency Injection with Unity - Patterns and Practices per le informazioni più utili come le proprietà di iniezione e simili.

Spero che questo aiuti.

1

Non pensare che importi se si hanno le classi nello stesso file o meno. Unity deve sapere come creare l'istanza data il tipo.

Se si utilizza RegisterInstance, l'oggetto specifico passato come argomento viene restituito ogni volta che viene chiamato Resolve per il tipo. Se il tipo è registrato usando RegisterType (o non registrato affatto per le classi concrete), Unity tenterà di creare un'istanza del tipo utilizzando il costruttore con il maggior numero di argomenti. Per ciascun tipo di parametro, Unity proverà a risolverli ricorsivamente.

La registrazione di associazioni per tipi di interfaccia a tipi concreti è obbligatoria ma la registrazione di tipi concreti è facoltativa.

codice di esempio:

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

Problemi correlati