Yes, that approach looks like it would handle all the currently-loaded 
assemblies. I'm not sure that it would help with assemblies which were 
referenced but hadn't yet been loaded.

Ultimately, it depends on what this is for - personally I'd expect that in 
most cases it would be fine just to explicitly state up-front which 
descriptors (or at least assemblies) were involved.

Jon


On Wednesday, 9 March 2016 17:15:23 UTC, Benjamin Krämer wrote:
>
> Hi Jon,
>
> Am Mittwoch, 9. März 2016 13:59:32 UTC+1 schrieb Jon Skeet:
>>
>> Indeed there isn't. It's not clear to me at what point messages would get 
>> registered - after all, a new assembly with extra messages could be loaded 
>> at any point.
>>
>
> I'm not completely up to date on module initialization in CLR. Is there 
> still no native language support for it? I only know this 7 year old 
> workaround, but this is done after building: 
> http://einaregilsson.com/module-initializers-in-csharp/ Also I just found 
> this post about a nuget package: 
> http://geertvanhorrik.com/2013/06/28/assembly-constructors-and-initializers-using-c/
>  
> Also not a good solution for including it in a library... Would be a bit 
> sad if Microsoft still offers no support to access this CLR feature. I 
> understand that static constructors are only called when the type is 
> referenced for the first time.
>
> Another possible (also if not as performant) option I successfully tried 
> was reflection. 
> https://github.com/Falco20019/protobuf/commit/74e5a82593787610f2207423bf3a8a8449a78813
>  
> By introducing a common interface, you can look them up in the AppDomain. 
> Here is the test class I used to generate a TypeRegistry from all currently 
> loaded assemblies. This is not cached but calculated on request since new 
> assemblies can be introduced as you said.
>
> public static TypeRegistry GetTypeRegistry()
> {
>     List<FileDescriptor> descriptors = new List<FileDescriptor>();
>     AppDomain.CurrentDomain.GetAssemblies()
>         .SelectMany(s => s.GetTypes())
>         .Where(p => typeof(IReflection).IsAssignableFrom(p) && !p.
> IsInterface)
>         .ToList()
>         .ForEach(type =>
>         {
>             var pi = type.GetProperty("Descriptor", BindingFlags.Public | 
> BindingFlags.Static);
>             var value = pi.GetValue(null);
>             descriptors.Add((FileDescriptor)value);
>         });
>
>     return TypeRegistry.FromFiles(descriptors);
> }
>
> Calling GetValue on the property initializes the type and returns the 
> descriptor. If you only want to call your static constructor for all 
> classes, you could use 
>
> System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
>
> This is better than invoking TypeInitializer which leads to the 
> constructor being called multiple times (as you also wrote on StackOverflow 
> 6 years ago :) ).
>
> I also thought about just using IMessage for the lookup and use Descriptor 
> to initialize the TypeRegistry with FromMessages, but this would finds a 
> lot more types which would make the reflection part slower.
>

-- 
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