C#实现IOC

十年前的我雄心勃勃,那时候刚从N软离职,在卡离职的20几天闭关决心写一套框架。虽然后面没实用,不过后续的框架借鉴了很多当时的经验和设计。

面向对象的三大特性是:
1.封装
2.继承
3.多态

C#作为面向对象语言。同时也是高级语言,如果不能把面向对象的特性用起来,那么是浪费的。在我看来没有多态的程序是没有灵魂的。多态借助接口实现,但是直接在接口对象后面new实现对象实际是没实现多态的。如下:

IStudent stu=new Student();

上面这种代码其实不是面向接口编程,因为改Student实现类还得改new代码编译。达不到多态的效果。为了实现多态就需要借助设计模式的工程模式。借助C#的反射按配置反射得到实现对象赋值给接口对象。即实现类可配置,后期我实现的各个程序都是按面向接口可配置实现的。在N软离职空窗期我构想实现一套框架体系,名为“GreenFram”。代码如下:
Green源码
在这里插入图片描述

框架包含“依赖注入”,“AOP面向切面”,“数据访问层”,“公共层”。首先需要使用IOC依赖注入功能探索。

通过解析Xml配置后用C#反射实现容器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Xml.Linq;
using System.Reflection;
namespace MyselfIocTest
{
    public class MyXmlFactory
    {
        private IDictionary<string, object> objList = new Dictionary<string, object>();

        public MyXmlFactory(string xmlFileName)
        {
            InitObjects(xmlFileName);//实例Ioc容器
            DiObject(xmlFileName);//属性注入
        }

        /// <summary>
        /// 实例Ioc容器
        /// </summary>
        /// <param name="xmlFileName">配置文件路径名</param>
        private void InitObjects(string xmlFileName)
        {
            XElement root = XElement.Load(xmlFileName);
            var objects = from obj in root.Elements("object") select obj;


            //无参构造函数
            objList = objects.Where(obj=>obj.Element("constructor-arg") == null).ToDictionary(
                k => k.Attribute("id").Value
                ,v => { string typeName = v.Attribute("type").Value
                    ; Type type = Type.GetType(typeName)
                        ; return Activator.CreateInstance(type); }
                );


            //有参构造函数
            foreach(XElement elem in objects.Where(obj=>obj.Element("constructor-arg")!=null))
            {
                string id = elem.Attribute("id").Value;
                string typeName = elem.Attribute("type").Value;
                Type type = Type.GetType(typeName);
                var args = from property in type.GetConstructors()[0].GetParameters()
                           join e1 in elem.Elements("constructor-arg")
                           on property.Name equals e1.Attribute("name").Value
                           select Convert.ChangeType(e1.Attribute("value").Value, property.ParameterType);
                object obj = Activator.CreateInstance(type, args.ToArray());
                objList.Add(id, obj);
            }
        }

        /// <summary>
        /// 属性注入
        /// </summary>
        private void DiObject(string fileName)
        {
            XElement root = XElement.Load(fileName);
            var objects = from obj in root.Elements("object") select obj;
            foreach (KeyValuePair<string, object> item in objList)
            {
                foreach (var e1 in objects.Where(e => e.Attribute("id").Value == item.Key).Elements("property"))
                {
                    Type type = item.Value.GetType();
                    foreach (PropertyInfo property in type.GetProperties())
                    {
                        if (property.Name == e1.Attribute("name").Value)
                        {
                            if (e1.Attribute("value") != null)
                            {
                                if (e1.Attribute("value").Value == "")
                                {
                                    Console.WriteLine("警告:"+e1.Attribute("name").Value + "的属性值为空");
                                }
                                property.SetValue(item.Value, Convert.ChangeType(e1.Attribute("value").Value, property.PropertyType), null);
                            }
                            else if (e1.Attribute("ref") != null)
                            {
                                object refObject = null;
                                if (objList.ContainsKey(e1.Attribute("ref").Value))
                                {
                                    refObject = objList[e1.Attribute("ref").Value];
                                }
                                else
                                {
                                    Console.WriteLine(e1.Attribute("name").Value + "没有参照对象,请确定已注册");
                                }
                                property.SetValue(item.Value, refObject, null);
                            }


                        }



                    }
                }
            }
        }



        /// <summary>
        /// 获得对象
        /// </summary>
        /// <param name="objName">对象标示名</param>
        /// <returns></returns>
        public object GetObject(string objName)
        {
            object obj = null;
            if (objList.ContainsKey(objName))
            {
                obj = objList[objName];
            }
            return obj;
        }
    }
}

配置对象

<?xml version="1.0" encoding="utf-8"?>
<objects >
  <object id="Student" type="MyselfIocTest.Student">
  <!--构造器注入-->   
 <constructor-arg name="name" value="张联珠"></constructor-arg>
  <property name="MyTeacher" ref="Teacher"></property>
  </object>

  <object id="Teacher" type="MyselfIocTest.Teacher">
  <!--构造器注入-->   
 <constructor-arg name="name" value="张三"></constructor-arg>
  </object>
</objects>

使用容器代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyselfIocTest
{
    class Program
    {
        static void Main(string[] args)
        {
            MyXmlFactory myXmlFactory = new MyXmlFactory("myConfig.xml");
            Student student = (Student)myXmlFactory.GetObject("Student");
            Teacher t = (Teacher)myXmlFactory.GetObject("Teacher");
            t.Say();
            if (student != null)
            {
                student.Say();
            }
            Console.Read();
        }
    }
}

简单IOC
这样就可以通过配置得到对象实现new解耦,达到依赖注入。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Unity中使用IoC(Inversion of Control,控制反转)容器可以帮助我们更好地管理和组织代码,提高代码的可测试性和可维护性。下面是在C# Unity中使用IoC容器的一些基本知识: 1. 什么是IoC容器? IoC容器是一个用于管理对象创建和依赖注入的工具。它实现了控制反转的原则,将对象的创建和依赖关系的解析交给容器来负责,而不是由应用程序手动管理。 2. 如何在Unity中使用IoC容器? Unity框架本身就提供了一个轻量级的IoC容器,可以通过安装Unity NuGet包来使用。可以使用容器注册和解析依赖关系,以及进行对象的生命周期管理。 3. 如何注册依赖关系? 可以使用Unity容器的RegisterType方法或RegisterInstance方法来注册依赖关系。RegisterType方法用于注册接口和实现的映射关系,RegisterInstance方法用于注册单例对象。 4. 如何解析依赖关系? 可以使用Unity容器的Resolve方法来解析依赖关系。当需要一个对象时,可以通过容器解析该对象及其依赖的所有对象。 5. 如何进行对象的生命周期管理? Unity容器提供了不同的生命周期管理选项,如Transient、Singleton、PerThread等。可以根据需求选择适合的生命周期管理方式。 6. 如何在Unity中使用IoC容器实现依赖注入? 可以将依赖的接口作为构造函数的参数,在需要使用该接口的地方使用依赖注入。Unity容器会自动解析依赖关系并注入相应的实现对象。 使用IoC容器可以减少手动管理对象创建和依赖关系的工作量,提高代码的可测试性和可维护性。但需要注意合理使用IoC容器,避免滥用导致代码复杂性增加。建议深入学习IoC容器的原理和使用方法,以更好地应用于实际项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值