C#通过反射实现简单的控制反转和依赖注入(一)
Java项目中通过@Autowire便可以实现将对象实例化到指定的字段,无需手动new一个对象出来,用起来非常方便,因为Java类加载器在在加载过程会将扫描所有@Servie、@Mapper、@Component等标注的所有类,并创建实例保存在Spring容器中,然后扫描所有@Aotuwire的字段,通过反射将对应的实例注入到类中,因此不需要对对象进行实例化,这都是是依赖于Ioc和DI,即控制反转和依赖注入
@Service public class SysDeptServiceImpl implements SysDeptService { @Autowired private SysDeptMapper sysDeptMapper; }
@Mapper public interface SysDeptMapper { int deleteByPrimaryKey(Long id); int insert(SysDept record); int insertSelective(SysDept record); SysDept selectByPrimaryKey(Long id); int updateByPrimaryKeySelective(SysDept record); int updateByPrimaryKey(SysDept record); List<SysDept> findPage(); List<SysDept> findAll(); }
依赖注入主要有
接口注入、字段、属性注入、构造函数注入、方法注入等方式
C#实现字段注入
通过 FieldInfo 的 setValue实现
/// <summary>设置给定对象支持的字段的值。</summary> /// <param name="obj">将设置其字段值的对象。</param> /// <param name="value">要分配给字段的值。</param> /// <exception cref="T:System.FieldAccessException"> /// 在适用于 Windows 应用商店应用的 .NET 或可移植类库中,改为捕获基类异常 <see cref="T:System.MemberAccessException" />。 /// /// 调用方没有权限来访问此字段。 /// </exception> /// <exception cref="T:System.Reflection.TargetException"> /// 在适用于 Windows 应用商店应用的 .NET 或可移植类库中,改为捕获 <see cref="T:System.Exception" />。 /// /// <paramref name="obj" /> 参数是 <see langword="null" /> 且该字段为实例字段。 /// </exception> /// <exception cref="T:System.ArgumentException"> /// 对象上不存在该字段。 /// /// - 或 - /// /// <paramref name="value" /> 参数不能转换且不能存储在字段中。 /// </exception> [DebuggerStepThrough] [DebuggerHidden] public void SetValue(object obj, object value);
简单例子如下
/// <summary> /// 字段注入 /// </summary> /// <param name="instance"></param> private static void AutoWireFields(object instance) { var fields = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); var fieldInfos = fields.Where(i => i.IsPrivate && i.Name.StartsWith("_") && i.FieldType!=typeof(string)).ToList(); fieldInfos.ForEach(f => f.SetValue(instance, Activator.CreateInstance(f.FieldType))); }
构造函数注入
public static void AutoWireConstructor(object instance, Type type) { var constructorInfos = instance.GetType().GetConstructors(); if (constructorInfos.Any()) { foreach (var item in constructorInfos) { var cotrParams = new Object[] { Activator.CreateInstance(type) }; dynamic some = item.Invoke(cotrParams);//调用构造函数// } } }
属性注入
public static void AutoWireProperties(object instance,Type type) { var properties = instance.GetType().GetProperties(); if (properties.Any()) { foreach (var obj in properties) { var diInstance = Activator.CreateInstance(type); PropertyInfo pi2 = instance.GetType().GetProperty(obj.Name); pi2.SetValue(instance, diInstance, null); } } }