-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Creating new TypeName without reparsing #102263
Comments
Tagging subscribers to this area: @dotnet/area-system-reflection-metadata |
Should we rather address the more general problem of creating TypeName of any shape through constructors or factory methods? It happens that the AssemblyName case showed up with the binary formatter. I think it is a tell-take of a general need for creating arbitrary TypeNames. |
All I am not saying no, I just don't have a clear vision of how these APIs would look like. |
Why do the strings need to be validated? Type names can be anything. |
Ah, it is because the APIs returned escaped names. The escaping validation should be very cheap, much cheaper than parsing. The more I see the issues with the name escaping, the more I think that it was a bad design decision to make the Name and FullName properties to match reflection behavior. Should we revisit that? The APIs can look like this: public static TypeName MakeSimpleTypeName(string fullName, TypeName? declaringType = null, AssemblyNameInfo? assemblyInfo = null);
public static TypeName MakeArrayTypeName(TypeName elementType);
public static TypeName MakeArrayTypeName(TypeName elementType, int rank);
public static TypeName MakePointerTypeName(TypeName elementType);
public static TypeName MakeByRefTypeName(TypeName elementType);
public static TypeName MakeGenericTypeName(TypeName genericTypeDefinition, ImmutableArray<TypeName> typeArguments);
// Matches Unscape method proposed in #101774
public static string Escape(string name); |
But it allows for things like I know it may sound silly but IMO we would not have that problem if we would simply forbid using certain characters without the ability to escape them in the first place. |
Yeah, that's the conundrum when you want to use this together with reflection. It is hard to tell how common this use case is going to be. Anyway, I edited my suggestion at #102263 (comment) to include
It would produce non-compliant type name parser. It may be ok for BF-specific parser. I do not think it is ok for S.R.Metadata or the runtime that need compliant and backward compatible type name parsers. It would be a needless breaking change to drop support for escaped type names. |
Moving to v10 since we have reached the "feature complete" milestone; still in API review backlog. |
namespace System.Reflection.Metadata;
public partial class TypeName
{
public TypeName MakeSZArrayTypeName();
public TypeName MakeArrayTypeName(int rank);
public TypeName MakePointerTypeName();
public TypeName MakeByRefTypeName();
public TypeName MakeGenericTypeName(ImmutableArray<TypeName> typeArguments);
public static TypeName CreateSimpleTypeName(
string metadataName,
TypeName? declaringType = null,
AssemblyNameInfo? assemblyInfo = null);
} |
I've adopted my initial implementation (#103713) to the approved API in 9a0cd58. So far, all The introduction of Example: Same goes for escaping. If we have a name that consists of escaped escape character followed by an escaped special character like Example: In my opinion, since But we still need the ability to replace public class TypeName
{
- public static TypeName CreateSimpleTypeName(string metadataName, TypeName? declaringType = null, AssemblyNameInfo? assemblyInfo = null);
+ public TypeName MakeSimpleTypeName(TypeName? declaringType = null, AssemblyNameInfo? assemblyInfo = null);
} That method would throw for non-simple names and prevent the users from creating invalid instances. I've implemented it in aabe51b |
If you pass
|
@jkotas big thanks for the clarification, now it all makes sense. Since I've finished implementing #103713 and I need just one more method: namespace System.Reflection.Metadata;
public partial class TypeName
{
public TypeName MakeSZArrayTypeName();
public TypeName MakeArrayTypeName(int rank);
public TypeName MakePointerTypeName();
public TypeName MakeByRefTypeName();
public TypeName MakeGenericTypeName(ImmutableArray<TypeName> typeArguments);
+ public TypeName MakeSimpleTypeName(AssemblyNameInfo? assemblyInfo);
public static TypeName CreateSimpleTypeName(
string metadataName,
TypeName? declaringType = null,
AssemblyNameInfo? assemblyInfo = null);
} I am going to create a new issue with the proposal for it. |
I do not see why escaping the type name passed into |
I think it depends on how you treat the comparison of current char vs chars that needs to be escaped. For me, assuming that we have |
This is not a general-purpose escaping with arbitrary escape characters. The number of characters that need escaping is very small (7 to be exact) and set in stone. So it is |
@adamsitnik is there anything left to do here? Can we close this issue? |
The |
That's correct. On the other hand, I am not aware of any place that can use the API of this shape currently, so we may want to let this issue linger until this need materializes. There are a few places that do raw type name escaping (e.g. Line 103 in 2a1b35e
|
I agree, let's wait 👍 . |
Background and motivation
As we have started using the new
TypeName
APIs all over the place, I've realized that it would be very nice to have the ability to create a newTypeName
instance with givenAssemblyNameInfo
without the need of re-parsing the concatenated input again.For example, in BinaryFormatter the type and library names are provided separately (#102014 (comment)), I would like to join them without re-parsing the whole thing again.
API Proposal
API Usage
Risks
Some users may miss the fact that the API creates a new instance of
TypeName
rather than mutating the current instance.Sample implementation with tests and usages in dotnet/runtime available at #103713
The text was updated successfully, but these errors were encountered: