.net反射存在的问题及优化技术--反射之依赖注入的改进

.net反射存在的问题及优化技术--反射之依赖注入的改进

2926发表于2016-08-27

有时我们为了把具体的逻辑实现从客户端调用解耦出来就会用到依赖注入,常用的依赖注入是允许在用户配置文件中配置程序集和类。这样程序就要根据配置文件利用反射来动态的加载程序集,创建相应的类对象来完成相应的操作。这要反射操作如果调用比较频繁,反射的开销是不能忽视的。Microsoft .NET在命名空间System.Reflection.Emit下为我们提供了一些API可以用编程的形式生成高性能的IL代码,这基于设计时的创建任何对象,这项技术可以用来减少每次利用反射来动态调用开销。
依赖类的接口:

public interface ISecurityProvider
{
    bool ValidateUser(string userId, string password);
    List<User> GetUsersList();
}
实际的具体实现类:动态的调用:
public class DefaultSecurityProvider : ISecurityProvider
{
    public bool ValidateUser(string userId, string password)
    {
        //...
    }
    public List<User> GetUsersIist()
    {
        //...
    }
}

上面代码的缺点&劣势

1、每次都要通过反射来动态创建所请求类的对象。

2、通过反射来动态创建所对象代价是很大的。

优化方案

定义一个创建实例的委托:

public delegate object CreateInstanceDelegate(); 

上面的委托就是利用Microsoft .NET轻量代码生成技术用于动态映射方法。同样定义一个字典是用来缓存类型对应创建对象的委托:

private static Dictionary<Type, CreateInstanceDelegate> 
    _createInstanceDelegateList = new Dictionary<Type, CreateInstanceDelegate>();

下面是一个具体类型在运行是通过IL生成技术动态创建对象的函数:

public static CreateInstanceDelegate ObjectInstantiater(Type objectType)
{
    CreateInstanceDelegate createInstanceDelegate;

    if (!_createInstanceDelegateList.TryGetValue(objectType, 
        out createInstanceDelegate))
    {
        lock (objectType)
        {
            if (!_createInstanceDelegateList.TryGetValue(objectType, 
         out createInstanceDelegate))
            {
                // 创建一个方法      
                DynamicMethod dynamicMethod =
                    new DynamicMethod("Create_" + objectType.Name,
	           objectType, new Type[0]);

                // 获取默认的构造函数
                ConstructorInfo ctor = objectType.GetConstructor(new Type[0]);

                // 生成.NET中间语言
                ILGenerator ilgen = dynamicMethod.GetILGenerator();
                ilgen.Emit(OpCodes.Newobj, ctor);
                ilgen.Emit(OpCodes.Ret);

                //创建一个委托并缓存到字典中
                createInstanceDelegate = (CreateInstanceDelegate)dynamicMethod
                    .CreateDelegate(typeof(CreateInstanceDelegate));
                _createInstanceDelegateList[objectType] = createInstanceDelegate;
            }
        }
    }
    return createInstanceDelegate; // 返回对象创建的委托对象
}  

最后使用这个创建对象的工厂方法:

private void CreateInstance()
{
    Type classType = 
   Type.GetType("DefaultSecurityProvider, AssemblyName");

    CreateInstanceDelegate createInstance = ObjectInstantiater(classType);

    ISecurityProvider employeeInstance = createInstance() as ISecurityProvider;
}  

上面的实例通过使用System.Reflection.Emit命名空间下面提供的API用编程的方式来创建一个代理方法来静态的创建所依赖的对象。一旦这个代理方法被创建了一次就会缓存下来,以备将来复用。

利用这上面技术的优点&优势

1、所依赖的类的对象使用委托指向的方法静态的创建
2、这项技术有助于避免来反射来初创建初始化对象

小编蓝狐