//private void BuildInputOutputValueTypes() //{ // if (_primaryContext.OutputType.IsSymbols()) // { // throw new Exception("we are not support ISymbolCollection<> output right now, you can use an Gather method to merge it into a single ISymbol<>"); // } // Trace.Assert(_primaryContext.InputType.IsSymbol() && _primaryContext.InputType.IsGenericType); // Trace.Assert(_primaryContext.OutputType.IsSymbol() && _primaryContext.OutputType.IsGenericType); // _inputValueType = _primaryContext.InputType.GetGenericArguments()[0]; // _outputValueType = _primaryContext.OutputType.GetGenericArguments()[0]; //} private void BuildServiceClientsRdsn() { foreach (var s in _contexts.SelectMany(c => c.Services).DistinctBy(s => s.Key.Member.Name)) { SpecProviderManager.Instance().GetProvider(s.Value.Spec.SType).GenerateClientDeclaration(_builder, s.Key, s.Value); } }
private void BuildServiceCallsRdsn(string serviceName) { var calls = new HashSet <string>(); foreach (var s in _contexts.SelectMany(c => c.ServiceCalls)) { Trace.Assert(s.Key.Object != null && s.Key.Object.NodeType == ExpressionType.MemberAccess); var callName = s.Key.Method.Name; var respTypeName = s.Key.Type.GetCompilableTypeName(_rewrittenTypes); var reqTypeName = s.Key.Arguments[0].Type.GetCompilableTypeName(_rewrittenTypes); var call = "Call_" + s.Value.PlainTypeName() + "_" + callName; if (!calls.Add(call + ":" + reqTypeName)) { continue; } _builder.AppendLine("private " + respTypeName + " " + call + "( " + reqTypeName + " req)"); _builder.BeginBlock(); var provider = SpecProviderManager.Instance().GetProvider(s.Value.Spec.SType); provider.GenerateClientCall(_builder, s.Key, s.Value, _rewrittenTypes); _builder.EndBlock(); _builder.AppendLine(); } }
private static ServicePlan Compile(Dictionary <MethodInfo, MethodCallExpression> expressions, object serviceObject) { // step: collect all types, methods, variables referenced in this expression var workerQueue = new Queue <KeyValuePair <MethodInfo, MethodCallExpression> >(); foreach (var exp in expressions) { workerQueue.Enqueue(new KeyValuePair <MethodInfo, MethodCallExpression>(exp.Key, exp.Value)); } var contexts = new Dictionary <MethodInfo, QueryContext>(); while (workerQueue.Count > 0) { var exp = workerQueue.Dequeue(); var context = new QueryContext(serviceObject, exp.Value, exp.Key.Name); context.Collect(); contexts.Add(exp.Key, context); foreach (var s in context.ExternalComposedSerivce.Where(s => !contexts.ContainsKey(s.Key))) { workerQueue.Enqueue(new KeyValuePair <MethodInfo, MethodCallExpression>(s.Key, s.Value)); } } // step: prepare service plan var codeGenerator = new CodeGenerator(); var name = serviceObject.GetType().Name + "." + codeGenerator.AppId; var plan = new ServicePlan { DependentServices = contexts .SelectMany(c => c.Value.Services.Select(r => r.Value)) .DistinctBy(s => s.Url) .ToArray(), Package = new ServicePackage() }; SystemHelper.CreateOrCleanDirectory(name); // step: generate composed service code var sources = new HashSet <string>(); var libs = new HashSet <string>(); var dir = name + ".Source"; SystemHelper.CreateOrCleanDirectory(dir); libs.Add(Path.Combine(Environment.GetEnvironmentVariable("DSN_ROOT"), "lib", "dsn.dev.csharp.dll")); libs.Add(Path.Combine(Environment.GetEnvironmentVariable("DSN_ROOT"), "lib", "Thrift.dll")); var code = codeGenerator.BuildRdsn(serviceObject.GetType(), contexts.Select(c => c.Value).ToArray()); SystemHelper.StringToFile(code, Path.Combine(dir, name + ".cs")); sources.Add(Path.Combine(dir, name + ".cs")); libs.UnionWith(QueryContext.KnownLibs); // step: generate client code for all dependent services foreach (var s in contexts .SelectMany(c => c.Value.Services.Select(r => r.Value)) .DistinctBy(s => s.PackageName) .Select(s => s.ExtractSpec())) { var provider = SpecProviderManager.Instance().GetProvider(s.SType); Trace.Assert(null != provider, "Language provider missing for type " + s.SType); LinkageInfo linkInfo; var err = provider.GenerateServiceClient(s, dir, ClientLanguage.Client_CSharp, ClientPlatform.Windows, out linkInfo); Trace.Assert(FlowErrorCode.Success == err); sources.UnionWith(linkInfo.Sources); libs.UnionWith(linkInfo.DynamicLibraries); } // step: fill service plan plan.Package.Spec = new ServiceSpec { SType = ServiceSpecType.Thrift, MainSpecFile = serviceObject.GetType().Name + ".thrift", ReferencedSpecFiles = plan.DependentServices .DistinctBy(s => s.PackageName) .Where(s => s.Spec.SType == ServiceSpecType.Thrift) .SelectMany(s => { var spec = s.ExtractSpec(); var specFiles = new List <string> { spec.MainSpecFile }; SystemHelper.SafeCopy(Path.Combine(spec.Directory, spec.MainSpecFile), Path.Combine(name, spec.MainSpecFile), false); foreach (var ds in spec.ReferencedSpecFiles) { specFiles.Add(ds); SystemHelper.SafeCopy(Path.Combine(spec.Directory, ds), Path.Combine(name, ds), false); } return(specFiles); } ) .Distinct() .ToList(), Directory = name }; plan.Package.MainSpec = ServiceContract.GenerateStandAloneThriftSpec(serviceObject.GetType(), plan.Package.Spec.ReferencedSpecFiles); SystemHelper.StringToFile(plan.Package.MainSpec, Path.Combine(name, plan.Package.Spec.MainSpecFile)); if (SystemHelper.RunProcess("php.exe", Path.Combine(Environment.GetEnvironmentVariable("DSN_ROOT"), "bin", "dsn.generate_code.php") + " " + Path.Combine(name, plan.Package.Spec.MainSpecFile) + " csharp " + dir + " json layer3") == 0) { sources.Add(Path.Combine(dir, serviceObject.GetType().Name + ".client.cs")); sources.Add(Path.Combine(dir, serviceObject.GetType().Name + ".server.cs")); sources.Add(Path.Combine(dir, "ThriftJsonHelper.cs")); sources.Add(Path.Combine(dir, serviceObject.GetType().Name + ".main.composed.cs")); sources.Add(Path.Combine(dir, serviceObject.GetType().Name + ".code.definition.cs")); } else { Console.Write("php codegen failed"); } //grab thrift-generated files sources.UnionWith(Directory.GetFiles(Path.Combine(dir, "thrift"), "*.cs", SearchOption.AllDirectories)); // step: generate composed service package CSharpCompiler.ToDiskAssembly(sources.ToArray(), libs.ToArray(), new string[] { }, Path.Combine(name, name + ".exe"), true, true ); libs.Add(Path.Combine(Environment.GetEnvironmentVariable("DSN_ROOT"), "lib", "dsn.core.dll")); libs.Add(Path.Combine(Environment.GetEnvironmentVariable("DSN_ROOT"), "lib", "zookeeper_mt.dll")); foreach (var lib in libs.Where(lib => !lib.StartsWith("System."))) { SystemHelper.SafeCopy(lib, Path.Combine(name, Path.GetFileName(lib)), false); } //Console.ReadKey(); return(plan); }