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.