A similar question has been asked in Ordering of reflection requests in dotnet
But I'm hoping for a different answer... I'm writing a plugin for a program that uses reflection to interrogate plugins to find the entry point. Unfortunately it has a bug which means if it encounters an interface declaration during this process it crashes with an unhandled exception. I have spoken to the development team and this is unlikely to be fixed. This is extremely limiting for me for obvious reasons. One workaround I have already thought of is to have my assembly load another assembly with the interfaces in it, but for reasons I won't go into this is not a great solution. It was a while before I encountered this problem because for some reason my entry class always preceded my interfaces in the reflection enumeration order.
My question is, is there any way to influence the ordering of classes and interfaces in the assembly?
Note: I have already tried setting different accessibility levels on my interfaces but that doesn't work for me.
Cheers,
J
I'd bet the code using AppDomain.GetAssemblies() which are then inspected. The implementation of AppDomain.GetAssemblies() leads to an external method, so Reflector is of mostly no help here.
However, without actually trying it and inspecting the result, there are two logical options for the ordering of assemblies in the result:
Load order
Alphabetical order
In the first case you'd probably have to organize references among your assemblies and the load order in such a way that the foreign code finds the right assembly with the entrypoint class and stops. In the second case it would be a pure matter of naming the assemblies in a 'right' way but I doubt it's this case.
(However, the order may be completely different from the two above, e.g. 'mostly' random as well.)
In either case I think sooner or later the buggy code will encounter the problematic assembly and crash anyway. Thus the strong recommendation is: insist on having the bug fixed.
Related
What is the difference between c# and f# assemblies? Some flag maybe? I want to determine it using reflection API only
There's no single value to check that would tell you what you need, but there's a good amount of circumstancial evidence that you could look at - IlSpy is your friend if you want to explore it.
I would suggest you check for presence of these two indicators, either of them being present would mean you're likely looking at an F# assembly unless someone is really dedicated to mess things up for you.
FSharpInterfaceDataVersionAttribute on the assembly. This was my initial suggestion, however there are compiler flags that, when set, would prevent this attribute from being emitted: --standalone and --nointerfacedata. I find it highly doubtful either of them would be commonly used in the field, but the fact remains there are openly available ways of opting out from the attribute being emitted right now.
asm.GetCustomAttribute(typeof(FSharpInterfaceDataVersionAttribute))
Presence of StartupCode types. They're an artifact of how F# compiler compiles certain constructs, and it seems they're present even empty, so they should be highly reliable.
asm.GetTypes().Where(fun x -> x.FullName.StartsWith("<StartupCode$"))
In particular looking for a reference to FSharp.Core is not a great idea, as it would be commonly referenced from C# projects as well if you're working with mixed solutions (and there's nothing stopping anyone from just getting it off nuget).
I have a C# assembly that uses "$(FrameworkSDKDir)\Bin\NETFX 4.0 Tools\tlbexp.exe" "$(OutDir)My.dll" /out:"$(TLBDir)My.tlb" so that I can call it from native components
I am looking at
.tlh generated on 2 machines is different and it appears to be a similar problem, but my difference is in visual2010 the tlh is generated using one case, and in 2012, it is generated using a different case.
Even more interesting this just happened a day ago. I have a build from the 18th that worked just fine, and the code has not changed in either solutions for many days.
Any thoughts before i continue down the /Names option?
I cannot easily tell you what to do to solve this problem, just highlight why this is happening. It doesn't have much to do with Tlbexp.exe, it is generic behavior implemented in the type library support built into Windows.
It has a tricky problem to solve, it cannot make any assumptions about the kind of language that was used to generate the types. The troublemakers are languages that are case-insensitive, Visual Basic being the prime example. Also the original language for which type libraries were invented. The issue is that it may emit names that can have different casing in different declarations but identify the same type. If the type library would use the same casing then it could only ever be consumed by a language-insensitive compiler.
So it does something about it, the algorithm it uses can at best be described as crude however. It looks at any name, regardless of what part of a declaration it is used, then forces the casing of any subsequent same name it encounters to the same casing. The usual big surprises are caused by names of function arguments. They can change the name of a function if it happens to match. So an "item" argument, pretty common, can spoil the name of an "Item" property. Or the other way around.
The wild-card here is order, I suppose that could be half an explanation.
Best way to address the problem is to change the name so there is no longer a collision. You have no trouble finding them, it is the one that changed casing. You may have to iterate a few times to find them all. Given that it is usually the name of an argument that causes this, feel free to change the argument name. Just put an underscore after it for example, it doesn't break binary compatibility nor the client code.
Going over some legacy code, I ran into piece of code that was using reflection for loading some dll's that their source code was available (they were another project in the solution).
I was cracking my skull trying to figure out why it was done this way (naturally the code was not documented...).
My question is, can you think about any good reason for preferring to load an assembly via reflection rather than referencing it?
Yes, if you have a dynamic module system, where different DLLs should be loaded depending on conditions at runtime. We do this where I work; we do a license check for different optional modules that may be loaded into our system, and then only load the DLLs associated with each module if the license checks out. This prevents code that should never be executed from being loaded, which can both improve performance slightly and prevent bugs.
Dynamically loading DLLs may also allow you to drastically change functionality without changing any source code. The main assembly may for instance set in motion a discovery process where it finds all classes that implement some interface, and chooses which one to use depending on some runtime criterion.
These days you'll typically want to use MEF for this kind of task, but that's only been around since .NET 4.0, so there are probably many codebases out there that do it manually. (I don't know much about MEF. Maybe you have to do this part manually there as well.)
But anyway, the answer to your question is that there certainly are good reasons to dynamically load DLLs using reflection. Whether it applies in your case is impossible to say without more details.
Without knowing you specific project, noone here can tell you why it was done that way in your case.
But the general reasons are:
updateability: You can simply recompile and replace the updated libary instead of having to recompile and replace the whole application.
cooperation: if the interface is clear, that way multiple teams can work together. one for the main application and others for the dlls
reusability: sometimes you need the same functionality in multiple projects, so the same dll can be used again and again
extensability: in some cases you want to be able to later extend your program with plugins that where not present at shipment time. This can be realized using dlls.
I hope this helps you understand some of your setup..
Reason for loading an assembly via reflection rather than referencing it?
Let us consider a scenario, where there are three classes with method DoWork() this method returns string, you are accessing it by checking the condition (strong type).
Now you have two more classes in two different DLL's how would you cope up the change?
1)You can add reference of new DLL's , change the conditional check and make it work.
2)You can use reflection , pass on condition and assembly name at run time, this allows you to add any number of functionality at runttime without any change of code in primary appliation.
The Assembly class has a GetReferencedAssemblies method that returns the
referenced assemblies. Is there a way to find what Types are referenced?
The CLR wont be able to tell you at runtime. You would have to do some serious static analysis of the source files - similar to the static analysis done by resharper or visual studio.
Static analysis is fairly major undertaking. You basically need a c# parser, a symbol table and plenty of time to work through all the cases that come up in abstract syntax trees.
Why can't the CLR tell you at run time? It is just in time compiled, this means that CLR bytcode is converted into machine code just before execution. Reflection only tells you stuff known statically at runtime about your types, and the CLR would only know if a type is referenced when the code is run. The CLR only knows when a type is loaded at execution time - at the point of just in time compilation.
Use System.Reflection.Assembly.GetTypes().
Types are not referenced separately from assemblies. If an assembly references another assembly, it automatically references (at least in the technical context) all the types within that assembly, as well. In order to get all the types defined (not referenced) in an assembly, you can use the Assembly.GetTypes method.
It may be possible, but sounds like a rather arduous task, to scan an assembly for which actual types it references (i.e. which types it actually invokes or otherwise mentions). This will probably involve working with IL. Something like this is best to be avoided.
Edit: Actually, when I think about it, this is not possible at all. Whatsoever. On a quite basic level. The thing is, types can be instantiated and referenced willy-nilly. It's not even uncommon for this to happen. Not to mention late binding. All this means trying to analyze an assembly for all the types it references is something like predicting the future.
Edit 2: Comments
While the question, as stated, isn't possible due to all sorts of dynamic references, it is possible greatly shrink all sorts of binary files using difference encoding. This basically allows you to get a file containing the differences between two binary files, which in the case of executables/libraries, tends to be vastly smaller than either of the actual files. Here are some applications that perform this operation. Note that bsdiff doesn't run on Windows, but there is a link to a port there, and you can find many more ports (including to .NET) with the aid of Google.
XDelta
bsdiff
If you'd look, you'll find many more such applications. One of the best parts is, they are totally self-contained and involve very little work on your part.
What determines the order of classes within an Assembly?
And.. is there a way to change it?
Additional info: you can check the ordering either through reflection yourself, or you can use a tool like ILDASM, disable the alphabetical sorting, and then you will also get the order.
Order seems to be in a strange way determined by the compiler.
I already tried some things.. like renaming the classes (order stays the same), also editing the .csproj file to change the order of the .cs files.
My main focus is VS2008, C#, .net 3.5.
Update: I do have a scenario where the order matters (external program going through my assembly through reflection) - and I need special order there.
Apart from this - you are totally right - order really should not matter.
I'm going to stick my neck out here and say this is an implementation detail and may well be decided by any particular compiler.
Since this is an implementation detail you shouldn't or needn't be concerned. Of course if this really is important (can't see why) you can always write your own IL.
I leave you with the following quote from Eric's blog:
Is compiling the same C# program twice guaranteed to produce the same
binary output?
No.
What determines the order of classes within an Assembly?
The compiler.
And.. is there a way to change it?
Write your own IL directly.
That being said, the order of the types within the assembly really doesn't matter. You can use the types with no regard to their order.