private void ReadReferencesRecursively(ReferencedAssembly assembly, AssemblyName[] references) { foreach (var reference in references) { if (_skipSystemAssemblies && (reference.Name == "mscorlib" || reference.Name == "System" || reference.Name.StartsWith("System.")) ) { continue; } if (_cache.ContainsKey(reference.FullName)) { _result.AddReference(assembly, _cache[reference.FullName]); continue; } AssemblyName[] referencedAssemblyReferences; var referencedAssembly = LoadReferencedAssembly(reference, out referencedAssemblyReferences); if (referencedAssembly.Category != Category.Missed) { var isNewReference = _result.AddReference(assembly, referencedAssembly); if (isNewReference) { ReadReferencesRecursively(referencedAssembly, referencedAssemblyReferences); } } else { _result.AddReference(assembly, referencedAssembly); } } }
public Type[] CreateDuckTypes(Type interfaceType, Type[] duckedTypes) { const string TYPE_PREFIX = "Duck"; String namespaceName = this.GetType().Namespace + "." + interfaceType.Name; CodeCompileUnit codeCU = new CodeCompileUnit(); CodeNamespace codeNsp = new CodeNamespace(namespaceName); codeCU.Namespaces.Add(codeNsp); //CodeTypeReference codeTRInterface = new CodeTypeReference(interfaceType); CodeTypeReference codeTRInterface = new CodeTypeReference(TypeX.Create(interfaceType).FullName); ReferenceList references = new ReferenceList(); // 遍历处理每一个需要代理的类 for (int i = 0; i < duckedTypes.Length; i++) { Type objectType = duckedTypes[i]; //CodeTypeReference codeTRObject = new CodeTypeReference(objectType); CodeTypeReference codeTRObject = new CodeTypeReference(TypeX.Create(objectType).FullName); references.AddReference(objectType); CodeTypeDeclaration codeType = new CodeTypeDeclaration(TYPE_PREFIX + i); codeNsp.Types.Add(codeType); codeType.TypeAttributes = TypeAttributes.Public; codeType.BaseTypes.Add(codeTRInterface); // 声明一个字段 CodeMemberField codeFldObj = new CodeMemberField(codeTRObject, "_obj"); codeType.Members.Add(codeFldObj); CodeFieldReferenceExpression codeFldRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), codeFldObj.Name); // 创建一个构造函数 CodeConstructor codeCtor = new CodeConstructor(); codeType.Members.Add(codeCtor); codeCtor.Attributes = MemberAttributes.Public; codeCtor.Parameters.Add(new CodeParameterDeclarationExpression(codeTRObject, "obj")); codeCtor.Statements.Add( new CodeAssignStatement( codeFldRef, new CodeArgumentReferenceExpression("obj") ) ); // 创建成员 CreateMember(interfaceType, objectType, codeType, references, codeFldRef); } #region 编译 CSharpCodeProvider codeprov = new CSharpCodeProvider(); #if DEBUG { StringWriter sw = new StringWriter(); codeprov.GenerateCodeFromCompileUnit(codeCU, sw, new CodeGeneratorOptions()); string code = sw.ToString(); Console.WriteLine(code); } #endif CompilerParameters compilerParams = new CompilerParameters(); compilerParams.GenerateInMemory = true; compilerParams.ReferencedAssemblies.Add(interfaceType.Assembly.Location); references.SetToCompilerParameters(compilerParams); CompilerResults cres = codeprov.CompileAssemblyFromDom(compilerParams, codeCU); if (cres.Errors.Count > 0) { StringWriter sw = new StringWriter(); foreach (CompilerError err in cres.Errors) { sw.WriteLine(err.ErrorText); } throw new InvalidOperationException("编译错误: \n\n" + sw.ToString()); } Assembly assembly = cres.CompiledAssembly; Type[] res = new Type[duckedTypes.Length]; for (int i = 0; i < duckedTypes.Length; i++) { res[i] = assembly.GetType(namespaceName + "." + TYPE_PREFIX + i); } return(res); #endregion }
void CreateMember(Type interfaceType, Type duckType, CodeTypeDeclaration codeType, ReferenceList references, CodeFieldReferenceExpression codeFldRef) { CodeTypeReference codeTRInterface = new CodeTypeReference(TypeX.Create(interfaceType).FullName); //// 找到duckType里面是否有公共的_obj; //FieldInfo fiObj = duckType.GetField("_obj", BindingFlags.Public | BindingFlags.Instance); //Type innerType = fiObj != null ? fiObj.FieldType : null; CodeFieldReferenceExpression fdRef = null; #region 方法 foreach (var mi in interfaceType.GetMethods()) { // 忽略专用名字的方法,如属性的get/set,还有构造函数 if ((mi.Attributes & MethodAttributes.SpecialName) != 0) { continue; } CodeMemberMethod codeMethod = new CodeMemberMethod(); codeType.Members.Add(codeMethod); codeMethod.Name = mi.Name; codeMethod.ReturnType = new CodeTypeReference(mi.ReturnType); codeMethod.PrivateImplementationType = codeTRInterface; references.AddReference(mi.ReturnType); ParameterInfo[] parameters = mi.GetParameters(); CodeArgumentReferenceExpression[] codeArgs = new CodeArgumentReferenceExpression[parameters.Length]; int n = 0; Type[] pits = new Type[parameters.Length]; foreach (ParameterInfo parameter in parameters) { pits[n] = parameter.ParameterType; references.AddReference(parameter.ParameterType); CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(parameter.ParameterType, parameter.Name); codeMethod.Parameters.Add(codeParam); codeArgs[n++] = new CodeArgumentReferenceExpression(parameter.Name); } CodeMethodInvokeExpression codeMethodInvoke = new CodeMethodInvokeExpression(FindMember(duckType, mi, codeFldRef), mi.Name, codeArgs); if (mi.ReturnType == typeof(void)) { codeMethod.Statements.Add(codeMethodInvoke); } else { codeMethod.Statements.Add(new CodeMethodReturnStatement(codeMethodInvoke)); } } #endregion #region 属性 foreach (PropertyInfo pi in interfaceType.GetProperties()) { CodeMemberProperty property = new CodeMemberProperty(); codeType.Members.Add(property); property.Name = pi.Name; property.Type = new CodeTypeReference(pi.PropertyType); property.Attributes = MemberAttributes.Public; property.PrivateImplementationType = codeTRInterface; references.AddReference(pi.PropertyType); ParameterInfo[] parameters = pi.GetIndexParameters(); CodeArgumentReferenceExpression[] args = new CodeArgumentReferenceExpression[parameters.Length]; int n = 0; foreach (ParameterInfo parameter in parameters) { CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(parameter.ParameterType, parameter.Name); property.Parameters.Add(codeParam); references.AddReference(parameter.ParameterType); CodeArgumentReferenceExpression codeArgRef = new CodeArgumentReferenceExpression(parameter.Name); args[n++] = codeArgRef; } fdRef = FindMember(duckType, pi, codeFldRef); if (pi.CanRead) { property.HasGet = true; if (args.Length == 0) { property.GetStatements.Add( new CodeMethodReturnStatement( new CodePropertyReferenceExpression( fdRef, pi.Name ) ) ); } else { property.GetStatements.Add( new CodeMethodReturnStatement( new CodeIndexerExpression( fdRef, args ) ) ); } } if (pi.CanWrite) { property.HasSet = true; if (args.Length == 0) { property.SetStatements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression( fdRef, pi.Name ), new CodePropertySetValueReferenceExpression() ) ); } else { property.SetStatements.Add( new CodeAssignStatement( new CodeIndexerExpression( fdRef, args ), new CodePropertySetValueReferenceExpression() ) ); } } } #endregion #region 事件 foreach (EventInfo ei in interfaceType.GetEvents()) { fdRef = FindMember(duckType, ei, codeFldRef); StringBuilder sbCode = new StringBuilder(); sbCode.Append("public event " + ei.EventHandlerType.FullName + " @" + ei.Name + "{"); //sbCode.Append("add {" + codeFldObj.Name + "." + ei.Name + "+=value;}"); //sbCode.Append("remove {" + codeFldObj.Name + "." + ei.Name + "-=value;}"); if (fdRef == codeFldRef) { sbCode.Append("add {" + codeFldRef.FieldName + "." + ei.Name + "+=value;}"); sbCode.Append("remove {" + codeFldRef.FieldName + "." + ei.Name + "-=value;}"); } else { sbCode.Append("add {" + fdRef.FieldName + "." + codeFldRef.FieldName + "." + ei.Name + "+=value;}"); sbCode.Append("remove {" + fdRef.FieldName + "." + codeFldRef.FieldName + "." + ei.Name + "-=value;}"); } sbCode.Append("}"); references.AddReference(ei.EventHandlerType); codeType.Members.Add(new CodeSnippetTypeMember(sbCode.ToString())); } #endregion #region 递归基接口 Type[] ts = interfaceType.GetInterfaces(); if (ts != null && ts.Length > 0) { foreach (Type item in ts) { CreateMember(item, duckType, codeType, references, codeFldRef); } } #endregion }
public Type[] CreateDuckTypes(Type interfaceType, Type[] duckedTypes) { const string TYPE_PREFIX = "Duck"; String namespaceName = this.GetType().Namespace + "." + interfaceType.Name; CodeCompileUnit codeCU = new CodeCompileUnit(); CodeNamespace codeNsp = new CodeNamespace(namespaceName); codeCU.Namespaces.Add(codeNsp); //CodeTypeReference codeTRInterface = new CodeTypeReference(interfaceType); CodeTypeReference codeTRInterface = new CodeTypeReference(TypeX.Create(interfaceType).FullName); ReferenceList references = new ReferenceList(); // 遍历处理每一个需要代理的类 for (int i = 0; i < duckedTypes.Length; i++) { Type objectType = duckedTypes[i]; //CodeTypeReference codeTRObject = new CodeTypeReference(objectType); CodeTypeReference codeTRObject = new CodeTypeReference(TypeX.Create(objectType).FullName); references.AddReference(objectType); CodeTypeDeclaration codeType = new CodeTypeDeclaration(TYPE_PREFIX + i); codeNsp.Types.Add(codeType); codeType.TypeAttributes = TypeAttributes.Public; codeType.BaseTypes.Add(codeTRInterface); // 声明一个字段 CodeMemberField codeFldObj = new CodeMemberField(codeTRObject, "_obj"); codeType.Members.Add(codeFldObj); CodeFieldReferenceExpression codeFldRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), codeFldObj.Name); // 创建一个构造函数 CodeConstructor codeCtor = new CodeConstructor(); codeType.Members.Add(codeCtor); codeCtor.Attributes = MemberAttributes.Public; codeCtor.Parameters.Add(new CodeParameterDeclarationExpression(codeTRObject, "obj")); codeCtor.Statements.Add( new CodeAssignStatement( codeFldRef, new CodeArgumentReferenceExpression("obj") ) ); // 创建成员 CreateMember(interfaceType, objectType, codeType, references, codeFldRef); } #region 编译 CSharpCodeProvider codeprov = new CSharpCodeProvider(); #if DEBUG { StringWriter sw = new StringWriter(); codeprov.GenerateCodeFromCompileUnit(codeCU, sw, new CodeGeneratorOptions()); string code = sw.ToString(); Console.WriteLine(code); } #endif CompilerParameters compilerParams = new CompilerParameters(); compilerParams.GenerateInMemory = true; compilerParams.ReferencedAssemblies.Add(interfaceType.Assembly.Location); references.SetToCompilerParameters(compilerParams); CompilerResults cres = codeprov.CompileAssemblyFromDom(compilerParams, codeCU); if (cres.Errors.Count > 0) { StringWriter sw = new StringWriter(); foreach (CompilerError err in cres.Errors) sw.WriteLine(err.ErrorText); throw new InvalidOperationException("编译错误: \n\n" + sw.ToString()); } Assembly assembly = cres.CompiledAssembly; Type[] res = new Type[duckedTypes.Length]; for (int i = 0; i < duckedTypes.Length; i++) { res[i] = assembly.GetType(namespaceName + "." + TYPE_PREFIX + i); } return res; #endregion }
void CreateMember(Type interfaceType, Type duckType, CodeTypeDeclaration codeType, ReferenceList references, CodeFieldReferenceExpression codeFldRef) { CodeTypeReference codeTRInterface = new CodeTypeReference(TypeX.Create(interfaceType).FullName); //// 找到duckType里面是否有公共的_obj; //FieldInfo fiObj = duckType.GetField("_obj", BindingFlags.Public | BindingFlags.Instance); //Type innerType = fiObj != null ? fiObj.FieldType : null; CodeFieldReferenceExpression fdRef = null; #region 方法 foreach (var mi in interfaceType.GetMethods()) { // 忽略专用名字的方法,如属性的get/set,还有构造函数 if ((mi.Attributes & MethodAttributes.SpecialName) != 0) continue; CodeMemberMethod codeMethod = new CodeMemberMethod(); codeType.Members.Add(codeMethod); codeMethod.Name = mi.Name; codeMethod.ReturnType = new CodeTypeReference(mi.ReturnType); codeMethod.PrivateImplementationType = codeTRInterface; references.AddReference(mi.ReturnType); ParameterInfo[] parameters = mi.GetParameters(); CodeArgumentReferenceExpression[] codeArgs = new CodeArgumentReferenceExpression[parameters.Length]; int n = 0; Type[] pits = new Type[parameters.Length]; foreach (ParameterInfo parameter in parameters) { pits[n] = parameter.ParameterType; references.AddReference(parameter.ParameterType); CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(parameter.ParameterType, parameter.Name); codeMethod.Parameters.Add(codeParam); codeArgs[n++] = new CodeArgumentReferenceExpression(parameter.Name); } CodeMethodInvokeExpression codeMethodInvoke = new CodeMethodInvokeExpression(FindMember(duckType, mi, codeFldRef), mi.Name, codeArgs); if (mi.ReturnType == typeof(void)) codeMethod.Statements.Add(codeMethodInvoke); else codeMethod.Statements.Add(new CodeMethodReturnStatement(codeMethodInvoke)); } #endregion #region 属性 foreach (PropertyInfo pi in interfaceType.GetProperties()) { CodeMemberProperty property = new CodeMemberProperty(); codeType.Members.Add(property); property.Name = pi.Name; property.Type = new CodeTypeReference(pi.PropertyType); property.Attributes = MemberAttributes.Public; property.PrivateImplementationType = codeTRInterface; references.AddReference(pi.PropertyType); ParameterInfo[] parameters = pi.GetIndexParameters(); CodeArgumentReferenceExpression[] args = new CodeArgumentReferenceExpression[parameters.Length]; int n = 0; foreach (ParameterInfo parameter in parameters) { CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(parameter.ParameterType, parameter.Name); property.Parameters.Add(codeParam); references.AddReference(parameter.ParameterType); CodeArgumentReferenceExpression codeArgRef = new CodeArgumentReferenceExpression(parameter.Name); args[n++] = codeArgRef; } fdRef = FindMember(duckType, pi, codeFldRef); if (pi.CanRead) { property.HasGet = true; if (args.Length == 0) { property.GetStatements.Add( new CodeMethodReturnStatement( new CodePropertyReferenceExpression( fdRef, pi.Name ) ) ); } else { property.GetStatements.Add( new CodeMethodReturnStatement( new CodeIndexerExpression( fdRef, args ) ) ); } } if (pi.CanWrite) { property.HasSet = true; if (args.Length == 0) { property.SetStatements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression( fdRef, pi.Name ), new CodePropertySetValueReferenceExpression() ) ); } else { property.SetStatements.Add( new CodeAssignStatement( new CodeIndexerExpression( fdRef, args ), new CodePropertySetValueReferenceExpression() ) ); } } } #endregion #region 事件 foreach (EventInfo ei in interfaceType.GetEvents()) { fdRef = FindMember(duckType, ei, codeFldRef); StringBuilder sbCode = new StringBuilder(); sbCode.Append("public event " + ei.EventHandlerType.FullName + " @" + ei.Name + "{"); //sbCode.Append("add {" + codeFldObj.Name + "." + ei.Name + "+=value;}"); //sbCode.Append("remove {" + codeFldObj.Name + "." + ei.Name + "-=value;}"); if (fdRef == codeFldRef) { sbCode.Append("add {" + codeFldRef.FieldName + "." + ei.Name + "+=value;}"); sbCode.Append("remove {" + codeFldRef.FieldName + "." + ei.Name + "-=value;}"); } else { sbCode.Append("add {" + fdRef.FieldName + "." + codeFldRef.FieldName + "." + ei.Name + "+=value;}"); sbCode.Append("remove {" + fdRef.FieldName + "." + codeFldRef.FieldName + "." + ei.Name + "-=value;}"); } sbCode.Append("}"); references.AddReference(ei.EventHandlerType); codeType.Members.Add(new CodeSnippetTypeMember(sbCode.ToString())); } #endregion #region 递归基接口 Type[] ts = interfaceType.GetInterfaces(); if (ts != null && ts.Length > 0) { foreach (Type item in ts) { CreateMember(item, duckType, codeType, references, codeFldRef); } } #endregion }