Hi,

I wanted to generate FileDescriptor dynamically from .proto without 
referencing, as in the given example we have reference Student.Interop.DTO 
so that we can get the StudentDTO.Descriptor and EmployeeDTO.Descriptor, so 
i wanted to avoid this reference.

*Example :*
namespace Student.WebApi
{    
    using System.Web.Http;
    using Framework.WebApi.Formatters;
    using Google.Protobuf.Reflection;
    using Repository;  
    using Student.Interop.DTO;  

    public class WebApiApplication : System.Web.HttpApplication
    {        
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            var json = 
GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            json.SerializerSettings.Converters.Add(new 
AnyJsonConverter(TypeRegistry.FromMessages(StudentDTO.Descriptor, 
EmployeeDTO.Descriptor)));
            
        }      
    }
}

So to achieve this following few steps i tried :

*Step 1* : Sample Proto i.e Student.proto which consist of message type i.e 
StudentDTO 
and EmployeeDTO

syntax = "proto3";
package AnalysisConsoleApplication;
import "google/protobuf/any.proto";
option csharp_namespace = "AnalysisConsoleApplication";

message StudentDTO
{ google.protobuf.Any Any = 1;
string USN = 2; 
string Name = 3;
string University = 4;
}
message EmployeeDTO
{ 
string Name = 1;
string Gender = 2;
}

Step 2 : I generated Student.pb by using below command i.e 

.\protoc.exe --proto_path=D:\Proto Proto\Student.proto --include_imports 
--descriptor_set_out=D:\AnalysisConsoleApplication\Student.pb

Step 3 : If i reference Google.Protobuf.3.0.0-beta2 in my 
SampleConsoleApplication and try to use FileDescriptor class then it will 
give error as recently in updated version FileDescriptor  is of Internal 
sealed class. so i clone the Google.Protobuf repository which was of 
Google.Protobuf.3.0.0-beta2 release time, at that time FileDescriptor class 
was public sealed class. Now my SampleConsoleApplication  solution will 
have another project which is of Google.Protobuf.

Note: SampleConsoleApplication zip file is been attached for detail 
understanding.

This code is from Actual generated C# file(Student.cs) from the given 
proto, but now next step we will create this below descriptorData dynamically 
from Student.pb
byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Cg1TdHVkZW50LnByb3RvEhpBbmFseXNpc0NvbnNvbGVBcHBsaWNhdGlvbhoZ",
            "Z29vZ2xlL3Byb3RvYnVmL2FueS5wcm90byJeCgpTdHVkZW50RFRPEiEKA0Fu",
            "eRgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnkSCwoDVVNOGAIgASgJEgwK",
            "BE5hbWUYAyABKAkSEgoKVW5pdmVyc2l0eRgEIAEoCSIrCgtFbXBsb3llZURU",
            "TxIMCgROYW1lGAEgASgJEg4KBkdlbmRlchgCIAEoCUIdqgIaQW5hbHlzaXND",
            "b25zb2xlQXBwbGljYXRpb25iBnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { 
global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, },
          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
            new 
pbr::GeneratedCodeInfo(typeof(global::AnalysisConsoleApplication.StudentDTO), 
global::AnalysisConsoleApplication.StudentDTO.Parser, new[]{ "Any", "USN", 
"Name", "University" }, null, null, null),
            new 
pbr::GeneratedCodeInfo(typeof(global::AnalysisConsoleApplication.EmployeeDTO), 
global::AnalysisConsoleApplication.EmployeeDTO.Parser, new[]{ "Name", 
"Gender" }, null, null, null)
          }));

Step 4: Now to generate descriptorData  dynamically from Student.pb, i have 
written the following code which gives the descriptorData in byte[]

//get the path of Student.pb
var path = string.Format("{0}/Student.pb", Path.GetDirectoryName(new 
Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath)); 
//create messageParser
MessageParser<FileDescriptorSet> messageParser = new 
MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
// open and read it
CodedInputStream stream = new CodedInputStream(new FileStream(path, 
FileMode.Open));
//Parses a message from the given coded input stream.
var data = messageParser .ParseFrom(stream);
//Covert to ByteString
var descriptorData  = data.File[0].ToByteString();   

Step 5: Last step to generate filedescriptor by calling 
FileDescriptor.FromGeneratedCode() 
which accepts 3 parameters
Parameter 1:  byte[] descriptorData -> this parameter we are able to 
generate dynamically as done in step 4 i.e   descriptorData.ToByteArray()  
     
Parameter 2:  FileDescriptor[] dependencies-> this takes all the 
dependencies.
Parameter 3: GeneratedCodeInfo generatedCodeInfo-> This has 
GeneratedCodeInfo(Type 
clrType, MessageParser parser, string[] propertyNames, string[] oneofNames, 
Type[] nestedEnums, GeneratedCodeInfo[] nestedTypes) out of this parameters 
i am not able to get clrtype dynamically.

*Here is the brief example of what i am expecting:*
typeof(global::SampleConsoleApplication.StudentDTO): this gives the type 
i.e clrtype of StudentDTO which is of public sealed class, which will be 
generated in  Student.cs by executing the Student.proto. But I am trying to 
get the clrtype without generating Student.cs, so because of which 
typeof(global::SampleConsoleApplication.StudentDTO) 
can't be used here.


-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Reply via email to