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