前置
Emit简单使用
public static void Main(string[] args){
// -- 创建程序集
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName("Example.Generator"),
AssemblyBuilderAccess.RunAndCollect);
// -- 创建模块
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Generators");
// -- 创建 Generator 类
TypeBuilder typeBuilder = moduleBuilder.DefineType("Generator");
// -- 创建构造函数
ConstructorBuilder constructorBuilder =
typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes)
// - 填充构造函数内需要执行的IL代码
ILGenerator constructGenerator = constructorBuilder.GetILGenerator();
// - 定义一个字符串
constructGenerator.Emit(OpCodes.Ldstr, "通过Emit构建构造函数中的逻辑代码");
// - 调用Console.WriteLine()输出这句话
constructGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
// - 返回
constructGenerator.Emit(OpCodes.Ret);
// -- 创建一个方法
MethodBuilder method = typeBuilder.DefineMethod("Start",
MethodAttributes.Public,
typeof(void),
new Type[] { typeof(string) });
// - 声明一个方法参数,名称为 name
method.DefineParameter(0, ParameterAttributes.None, "name");
// - 编写方法内部的IL代码
ILGenerator methodGenerator = method.GetILGenerator();
// - 将传入的参数 name 打印出来
methodGenerator.Emit(OpCodes.Ldarg_1);
methodGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
methodGenerator.Emit(OpCodes.Ret);
// -- 创建实例
Type instance = typeBuilder.CreateType();
object proxy = Activator.CreateInstance(instance);
// -- 调用
MethodInfo methodInfo = proxy.GetType().GetMethod("Start");
methodInfo.Invoke(proxy, new string[] { "Hello Elson" });
Console.ReadKey();
}
ServiceProviderEngine分析
(就不看具体的代码了,CallSiteRuntimeResolver中使用了反射都是比较好懂的,ILEmitResolverBuilder就是使用Emit把方法内容给描述出来然后使用代理调用,ExpressionResolverBuilder表达式树的构建)
- LEmitServiceProviderEngine
- 透过IL Emit的方式提供实例**(ILEmitResolverBuilder)**
- RuntimeServiceProviderEngine
- 透过反射取得实例**(CallSiteRuntimeResolver)**
- ExpressionsServiceProviderEngine
- 利用Expression Tree来产生实例**(ExpressionResolverBuilder)**
- DynamicServiceProviderEngine(继承了CompiledServiceProviderEngine)
- Dotnet core预设使用的方式,主要是透过当前的执行序池的请求数量决定要走上面3种的的哪一种,走ILEmitServiceProviderEngine或RuntimeServiceProviderEngine取决于runtime支不支持Reflection Emit
我认为这不过是作者写了3种不同的动态代理方式,为反射,表达式树和Emit。不同的代理在不同的场景下会有不一样的性能,或者是说是组合使用来弥补各自的一点不足。