C# 将动态对象映射到接口并向IoC注册

C# 将动态对象映射到接口并向IoC注册,c#,dynamic,unity-container,duck-typing,impromptu-interface,C#,Dynamic,Unity Container,Duck Typing,Impromptu Interface,我正在尝试注册接口的动态实现,这些接口将被注入到我的IoC容器(在本例中为Unity)创建的对象中 以下是我正在采取的高级方法: 从JSON文件动态加载属性列表。我目前正在使用它 将该动态对象映射到接口。我现在正在用这个 将该动态对象注册到接口类型的my IoC容器中 以下是应该“理论上”起作用的代码: 直到最后一行,一切都很好。Unity不喜欢我没有给它一个实际的接口实例,只是一个duck类型的实例 The type ImpromptuInterface.ActLikeCaster canno

我正在尝试注册接口的动态实现,这些接口将被注入到我的IoC容器(在本例中为Unity)创建的对象中

以下是我正在采取的高级方法:

  • 从JSON文件动态加载属性列表。我目前正在使用它
  • 将该动态对象映射到接口。我现在正在用这个
  • 将该动态对象注册到接口类型的my IoC容器中
  • 以下是应该“理论上”起作用的代码:

    直到最后一行,一切都很好。Unity不喜欢我没有给它一个实际的接口实例,只是一个duck类型的实例

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

    我为什么要这样做?我正试图通过将我的设置存储为JSON,定义映射到该JSON的接口,然后让我的IoC容器自动将正确的配置注入任何请求它的类来简化我复杂的应用程序配置。

    如果不需要使用接口,可以使用具体类型:

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

    ActLike
    用于静态键入动态对象,它至少需要对接口进行隐式转换。相反,使用
    DynamicActLike
    ,它将返回最终实例,而不需要先进行静态转换

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

    你作弊了。:-)在main方法中,指定类型(TestClass)。你能让你的代码在没有它的情况下工作吗?如果我用同样的方法,我可以让我的代码与接口一起工作。更新允许发送字符串。这确实很有帮助,我可以注册它。然而,当我试图解析该类型时,Unity抛出一个异常,即没有可访问的构造函数。我会给你一个投票,但我想我会使用Brandon的解决方案,并切换到一个具体的类型。嗯,我不确定什么是不可访问的,接口代理是公共的,并且有一个无参数构造函数。我现在一切正常。实际上,它的配置非常优雅。我很快就会在博客上写这件事。
    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
        }
    }
    
    var interfaceInstance = Impromptu.DynamicActLike(expando, interfaceType);