Open robertmuehsig opened 1 week ago
This is because binary compatibility is broken between target frameworks.
To achieve compatibility, you need to redirect the custom defined type to BCL defined type on higher versions, like this:
#if !NET7_0_OR_GREATER
// definition of RequiredMemberAttribute
#else
[TypeForwardedTo(typeof(RequiredMemberAttribute))]
#endif
@huoyaoyuan Thats a good hint, but
#if !NET7_0_OR_GREATER
namespace System.Runtime.CompilerServices
{
...
}
#else
[TypeForwardedTo(typeof(System.Runtime.CompilerServices.RequiredMemberAttribute))]
#endif
Results in error CS0116: A namespace cannot directly contain members such as fields, methods or statements
Are you typing correctly? The content under #if !NET7_0_OR_GREATER
should behave as-is.
Ok, this compiles:
#if !NET7_0_OR_GREATER
namespace System.Runtime.CompilerServices
{
/// <summary>Specifies that a type has required members or that a member is required.</summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
// #if SYSTEM_PRIVATE_CORELIB
public
// #else
// internal
// #endif
sealed class RequiredMemberAttribute : Attribute
{ }
}
#else
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.RequiredMemberAttribute))]
#endif
But the runtime error still appears:
System.TypeLoadException
HResult=0x80131522
Message=Could not load type 'System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute' from assembly 'BclTest.BclTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Source=System.Private.CoreLib
...
Found a workaround, but I'm still confused why.
If I add net8.0
in the TargetFrameworks of the Common Lib, then it works:
CommonTypes.csproj:
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
The TypeForwarding is not needed in this case.
But I wonder if this is by design or not?
If I add
net8.0
in the TargetFrameworks of the Common Lib, then it works:
In this case, the net8.0
version of unit test will use net8.0
version of Common, which uses the BCL version of attributes. It's expected to work in this case.
Description
Hi everyone, I'm not sure if this is the right repo or not, but I have an issue porting an application from .NET 6.0 to .NET 8.0. I'm not even sure if the "root" problem has something to do with the XmlSerializer or not.
Our scenario:
Our solution contains two main applications:
Both applications share some common types and the actual solution is "large" (~100 Projects, multiple web apps (e.g. WebApi, Admin App etc.)).
We try to stay up to date and want to use new languages features, that's why we have a project that contains "BCL-Types" like this:
This way we can use something like this in the Common area and don't bother if it is used from .NET 4.8 or not:
We use
XmlSerialization
for configuration stuff in our application and during the .NET 8 migration we found this RunTime Exception:Could not load type 'System.Runtime.CompilerServices.RequiredMemberAttribute' from assembly 'BclTest.BclTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Details
``` System.TypeLoadException HResult=0x80131522 Message=Could not load type 'System.Runtime.CompilerServices.RequiredMemberAttribute' from assembly 'BclTest.BclTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Source=System.Private.CoreLib StackTrace: at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type) at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext) at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg) at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType) at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit) at System.Xml.Serialization.TempAssembly.LoadGeneratedAssembly(Type type, String defaultNamespace, XmlSerializerImplementation& contract) at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) at CommonTypes.Person.DeserializeFromXml(String xml) in C:\Users\muehsig\source\repos\BclTest.BclTypes\CommonTypes\Person.cs:line 13 at TestProject1.UnitTest1.TestMethod1() in C:\Users\muehsig\source\repos\BclTest.BclTypes\TestProject1\UnitTest1.cs:line 33 at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) ```
It seems, that the XmlSerializer uses the "wrong" type during runtime.
Reproduction Steps
I made a small test repo here.
The smallest repo would be something like this:
In the Common Lib is a class like this:
In the .NET 8 Console App is a class like this:
In the Unit Test we have this:
Expected behavior
The Common type can be consumed from the .NET 4.8 client and the .NET 8 application and we can use modern language features in the .NET 8 application.
Actual behavior
With the TargetFrameworks in the BCL class like this "netstandard2.0,net8.0" the runtime error occures:
Could not load type 'System.Runtime.CompilerServices.RequiredMemberAttribute' from assembly 'BclTest.BclTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
I thought, that the TargetFramework might be "wrong" and I just use "netstandard2.0" in the BCL-Type lib, but then I get this compiler error:
Regression?
If I use "net6.0" instead of "net8.0" the issue is resolved, but the reason for this is simply this condition:
#if !NET7_0_OR_GREATER
Known Workarounds
No response
Configuration
.NET Framework 4.8 & .NET 8
Other information
No response