Closed koyote closed 2 years ago
@ericstj do you know where this should go?
a .Net Core project references a .Net Framework project
We do our best to make .NETCore work with .NETFramework libraries when the types exist, but in the case of this sample the type used by the .NETFramework library (System.Xaml) doesn't exist in the base shared framework.
You can change your .NETCore console project use the WindowsDesktop sdk instead, this contains WPF and will be able to resolve System.Xaml. That's probably the best workaround if you're compiling for windows.
There's not a great way to avoid this since reflection needs to be able to load assemblies in order to reflect.
One could argue that Assembly.GetCustomAttribute(type) shouldn't throw for other attribute types which cannot be resolved, since the caller passed in a resolved runtime type. This is probably correct most of the time, but it could be wrong in the case the type that wasn't resolved was actually forwarding to the type you were looking for. Perhaps FilterCustomAttributeRecord could be improved to only throw when it cannot resolve a type and that type has the same name as the one your filtering on. Otherwise it can ignore the unresolved type since it cannot possibly match the one its looking for (since it has a different name). That makes this a make reflection more resilient bug, so keeping this tagged as reflection.
/cc @steveharter
Per discussion with @GrabYourPitchforks the proposed work-around will not work in the general case because GetCustomAttributes(Type)
will enumerate all attributes that are compatible with Type
(checking base types). So just comparing the type name wouldn't work.
We could attempt to detect it the Type passed in is sealed, but then this becomes very specific.
A better work-around is to have System.Resources.ManifestBasedResourceGroveler
use GetCustomAttributeData
instead of GetCustomAttribute
so no attribute is instantiated. So moving to System.Resources.
Is this issue blocking any key scenarios?
@buyaa-n @tarekgh We think a better workaround would be to change ManifestBasedResourceGroveler
. See above.
GetCustomAttributeData doesn't avoid load of the assembly which defines the custom attribute. We would need something that just reads the metadata and doesn't try to create Type
objects (or activate types).
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. The system cannot find the file specified.
File name: 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
at System.ModuleHandle.ResolveMethodHandleInternalCore(RuntimeModule module, Int32 methodToken, IntPtr[] typeInstantiationContext, Int32 typeInstCount, IntPtr[] methodInstantiationContext, Int32 methodInstCount)
at System.ModuleHandle.ResolveMethodHandleInternal(RuntimeModule module, Int32 methodToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.CustomAttributeData..ctor(RuntimeModule scope, MetadataToken caCtorToken, ConstArray& blob)
at System.Reflection.CustomAttributeData.GetCustomAttributes(RuntimeModule module, Int32 tkTarget)
at System.Reflection.CustomAttributeData.GetCustomAttributesInternal(RuntimeAssembly target)
at System.Reflection.RuntimeAssembly.GetCustomAttributesData()
at custAttr.Program.GetCustomAttribute[T](Assembly assembly) in C:\Users\erics\source\repos\custAttr\custAttr\Program.cs:line 19
at custAttr.Program.Main(String[] args) in C:\Users\erics\source\repos\custAttr\custAttr\Program.cs:line 14
At that point then it seems that addressing this in the reflection layer would be a non-trivial work item, and per Steve's earlier comment it wouldn't solve the issue more generally anyway. The workaround previously given by retargeting the assembly against WindowsDesktop seems like it'd work since it'd allow the runtime to discover System.Xaml, no?
Retargeting the application to WindowsDesktop would work, but that's not always possible.
I think the problem in general is that Reflection isn't very resilient to dangling references. It's pretty unfortunate that this surfaces in the cases where the user isn't calling reflection but the framework itself needs to do so as part of its basic functionality.
Would xcopying System.Xaml alongside their app work? You know heaps more about assembly loading nits than I do. :)
(Edit: This still assumes changing the app, not the library.)
Would xcopying System.Xaml alongside their app work? You know heaps more about assembly loading nits than I do. :)
You can't just copy (.NET Core requires entry in .deps.json), but you can modify the project to add an assembly reference to System.Xaml and make sure it exists alongside their app.
I think the problem in general is that Reflection isn't very resilient to dangling references
Is there an argument to be made that the current behavior is desired -- i.e. that for consistency attributes should never be "skipped" because the attribute's Type can't be loaded?
Also what scenario this is current blocking, if any (WPF interop with existing assemblies?). The work-around of copying the assembly may be fine for this particular case.
If we think this scenario is important for 5.0 I will investigate potential fix.
The scenario blocked would be someone building a shared class-library that needs to work in both WPF apps and console apps. I suspect this is @koyote's scenario, but I could be wrong. The specific attribute is https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.xmlnsprefixattribute?view=netframework-4.8
The workaround would be move this attribute (and presumably any others like https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.xmlnsdefinitionattribute?view=netframework-4.8) into an assembly which is only used when WPF is available.
I don't think this scenario alone warrants prioritizing new API for 5.0, but I do think it's a ref count against reflection APIs that are resilient to missing types/assemblies.
The workaround would be move this attribute (and presumably any others like https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.xmlnsdefinitionattribute?view=netframework-4.8) into an assembly which is only used when WPF is available.
Along with a [TypeForwardedTo] in System.Xaml I assume.
Should we create a new WPF issue then? (keep this issue to track resilient missing types).
Right. This would need to happen in runtime repo, not WPF. WPF would need to react to it afterwards. We would need to add a System.Xaml shim to the set that we build in runtime, like WindowsBase. I’m not inclined to do this based on a single report for the reasons I called out above as well as the cost & complexity it adds.
If we hear from more folks that need this to work and can’t depend on WindowsDesktop we can reconsider. @vatsan-madhavan
Agree that a System.Xaml
shim is not yet warranted. A separate System.Xaml package (https://github.com/dotnet/wpf/issues/46) might be of help to those who can't retarget to windowsdesktop
entirely.
/cc @dotnet/wpf-developers
The scenario blocked would be someone building a shared class-library that needs to work in both WPF apps and console apps. I suspect this is @koyote's scenario, but I could be wrong. The specific attribute is https://docs.microsoft.com/en-us/dotnet/api/system.windows.markup.xmlnsprefixattribute?view=netframework-4.8
That is correct. The dotnet core application was extracted from a larger .net framework/WPF application and both share some assemblies including the .net framework assembly with the issue above.
You can't just copy (.NET Core requires entry in .deps.json), but you can modify the project to add an assembly reference to System.Xaml and make sure it exists alongside their app.
So if I understand correctly, the workaround is for the referenced project (or the dotnet core project?) to add a reference to System.Xaml?
Based on discussion, moving to Future. If there are additional scenarios or hits on this, please re-open.
@koyote here's the workarounds in order of precedence:
Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.
This process is part of our issue cleanup automation.
This issue will now be closed since it had been marked no-recent-activity
but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.
Hi,
When a .Net Core project references a .Net Framework project which has "XmlnsPrefix" set in AssemblyInfo AND we call code that accesses a resource in a .resx file, we get the following exception:
See attached Project: ConsoleApp2.zip