2016-06-14 4 views
15

Я читал об инъекции зависимостей Unity, и я понимаю, что это вещь, и что она позволяет вам вводить класс в интерфейс. Мне любопытно, есть ли у меня? В приведенном ниже сценарии есть TerrainGenerator и TileCreator в том же пространстве. Как я могу получить TileCreator в генераторе в качестве зависимости?Как я могу автоматически разрешать зависимости C#?

enter image description here

http://geekswithblogs.net/danielggarcia/archive/2014/01/23/introduction-to-dependency-injection-with-unity.aspx прогулки меня через регистрации типа, но я где-то читал, что до тех пор, как класс виден в разделе Unity активов он будет иметь возможность автоматического вводить его, я просто не могу понять из синтаксиса (если это возможно).

Update

Я мог поставить все классы в одном файле ... с большой системой, которая может быть очень раздражает. В то же время это подход, который я попробую - лучше, чем вообще не работать.

обновление Похоже, Unity должен быть в состоянии смотреть на класс конструктор и выполнять эти решения автоматически и ввести их в своем классе конструктор. Это возможно?

+3

Вы уверены, что [тег: Unity3D] имеет Dependency Injection? Вы уверены, что не читали о том, что Microsoft так же назвала [тег: единство]? Ссылка, на которую вы ссылаетесь, говорит о [Unity Microsoft] (https://msdn.microsoft.com/en-us/library/ff647202.aspx), а не о единстве Unity Technologies. Не совсем понятно, чего вы пытаетесь достичь, можете ли вы объяснить больше, что вы пытаетесь сделать? –

+0

Я определенно спрашиваю о Unity3d, я не понимал, что это были две разные вещи. Спасибо что подметил это. – Webnet

+2

Вы никогда не должны касаться конструктора класса «MonoBehavior». Ваш вопрос слишком сфокусирован на том, чтобы заставить работать инъекции зависимостей, и вы недостаточно объяснили о ***, почему вам нужно, чтобы в первую очередь включалась инъекция зависимости ***, это называется проблемой [XY] (http: // meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Исправьте свой вопрос и добавьте более подробную информацию о вашей реальной проблеме (* «есть TerrainGenerator и TileCreator в том же пространстве» *) и люди смогут помочь вам с этим ... –

ответ

8

Если вы ищете DI для двигателя Unity3D, может быть, это будет работать (я не использовал его, но обратная связь положительна) https://github.com/modesttree/Zenject

Если вы говорите о библиотеке Unity DI Microsoft, вы должны уметь это сделать:

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

Нет, вам не нужно использовать интерфейсы, вы можете регистрировать и разрешать конкретные типы.

Например, вы можете зарегистрировать TerrainGenerator и TileCreator следующим образом:

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

Не думайте, что это имеет значение, если у вас есть классы в одном файле или нет. Единство должно знать, как создать экземпляр с учетом типа.

Если используется 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

Смежные вопросы