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 protobuf+unsubscr...@googlegroups.com.
To post to this group, send email to protobuf@googlegroups.com.
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Reply via email to