3

Я пытаюсь зарегистрировать динамические реализации для интерфейсов, которые будут вставляться в объекты, созданные моим контейнером IoC (Unity в этом случае).Сопоставление динамического объекта с интерфейсом и регистрация с помощью IoC

Вот подход высокого уровня, я везу:

  1. Динамически загрузить список свойств из файла JSON. Я использую JSON.NET для этого сейчас.
  2. Отобразите этот динамический объект в интерфейс. В настоящее время я использую для этого Impromptu.
  3. Регистрация, что динамический объект с моей IoC контейнер для типа интерфейса

Вот код, который должен «теоретически» работа:

var configJson = File.ReadAllText(".\\Configuration\\DataCollector.json"); 
dynamic expando = JsonConvert.DeserializeObject(configJson); 
var container = new UnityContainer(); 
var interfaceType = Type.GetType("Manufacturing.Framework.Configuration.IDataCollectorConfiguration", true); 
var interfaceInstance = Impromptu.ActLike(expando, interfaceType); 

container.RegisterInstance(interfaceType, "IDataCollectorConfiguration", interfaceInstance, new ContainerControlledLifetimeManager()); 

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

The type ImpromptuInterface.ActLikeCaster cannot be assigned to variables of type Manufacturing.Framework.Configuration.IDataCollectorConfiguration 

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

+0

У меня сейчас все хорошо работает. Это на самом деле очень элегантно для конфигурации. Вскоре я расскажу об этом в блогах. –

ответ

2

Если вам не нужно использовать интерфейсы, вы могли бы получить с помощью конкретных типов:

using System; 
using Microsoft.Practices.Unity; 
using Newtonsoft.Json; 

namespace TestGrounds 
{ 
    public class TestClass 
    { 
     #region Properties 

     public int TestIntegerProperty { get; set; } 

     public string TestStringProperty { get; set; } 

     #endregion 
    } 

    internal class Program 
    { 
     #region Static Methods 

     private static void Main(string[] args) 
     { 
      const string json = 
       @"{ TestIntegerProperty: 1, TestStringProperty: 'Hello', AnotherTestPropertyToIgnore: 'Sup' }"; 

      registerDependencyFromJson<TestClass>(json); 

      Console.ReadKey(); 
     } 

     private static void registerDependencyFromJson<T>(string json) where T: class, new() 
     { 
      var deserializedObject = JsonConvert.DeserializeObject<T>(json); 
      var type = deserializedObject.GetType(); 
      var container = new UnityContainer(); 

      container.RegisterInstance(type, type.Name, deserializedObject, new ContainerControlledLifetimeManager()); 
     } 

     #endregion 
    } 
} 

Что может быть лучше в любом случае, так как интерфейсы могли бы потребоваться реализации метода на них, что любой вид проксирования Wouldn 't обрабатывать очень хорошо (хотя, я думаю, что у замка есть какой-то метод перехватчика). Бетонные типы избавляются от каких-либо допущений; единственным реальным требованием является новый().

Update:

Вот пример создания типа от имени строки, а также показывает недопустимый тип:

using System; 
using Microsoft.Practices.Unity; 
using Newtonsoft.Json; 

namespace TestGrounds 
{ 
    public class TestClass 
    { 
     #region Properties 

     public int TestIntegerProperty { get; set; } 

     public string TestStringProperty { get; set; } 

     #endregion 
    } 

    public class BadTestClass : TestClass 
    { 
     #region Properties 

     public double TestDoubleProperty { get; set; } 

     #endregion 

     #region Constructors 

     public BadTestClass(double testDouble) 
     { 
      TestDoubleProperty = testDouble; 
     } 

     #endregion 
    } 

    internal class Program 
    { 
     #region Static Methods 

     private static void Main(string[] args) 
     { 
      const string json = 
       @"{ TestIntegerProperty: 1, TestStringProperty: 'Hello', AnotherTestPropertyToIgnore: 'Sup' }"; 
      var type = Type.GetType("TestGrounds.TestClass", true); 
      var badType = Type.GetType("TestGrounds.BadTestClass", true); 

      registerDependencyFromJson(type, json); 
      try 
      { 
       registerDependencyFromJson(badType, json); 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 

      Console.ReadKey(); 
     } 

     private static void registerDependencyFromJson(Type type, string json) 
     { 
      // type requires a default constructor for this to work 
      var constructor = type.GetConstructor(Type.EmptyTypes); 
      if(constructor == null) 
      { 
       throw new ArgumentException("Type must have a parameterless constructor."); 
      } 

      var deserializedObject = JsonConvert.DeserializeObject(json, type); 
      var container = new UnityContainer(); 

      container.RegisterInstance(type, type.Name, deserializedObject, new ContainerControlledLifetimeManager()); 
     } 

     #endregion 
    } 
} 
+0

Вы обманули. :-) В основном методе вы указываете тип (TestClass). Можете ли вы заставить свой код работать без этого? Я могу заставить свой код работать с интерфейсами, если я делаю это так же. –

+0

Обновлено разрешение на отправку строк. –

1

ActLike предназначен для статической типизации динамических объектов, это требует, как минимум, неявный приведение к интерфейсу. Вместо этого используйте DynamicActLike, и он вернет окончательный экземпляр, не требуя первого статического броска.

var interfaceInstance = Impromptu.DynamicActLike(expando, interfaceType); 
+0

Это было определенно полезно, я смог зарегистрировать его. Однако, когда я пытаюсь разрешить этот тип, Unity выдает исключение, что нет доступного конструктора. Я дам вам верх, но я думаю, что я собираюсь пойти с решением Брэндона и перейти к конкретному типу. –

+0

huh, я не уверен, что было бы недоступно, прокси-интерфейсы являются общедоступными и имеют конструктор no-arg. – jbtule

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