Pretty straightforward question. I want to allow only DTO models in inputs (class & record types).
If I leave the class constraint only, I’m still able to put string in there. I want to not allow the primitive types.
If I put class, new(), it doesn’t allow string just as expected, but I’m not allowed to use positional records either which is a problem.
public class Asd
{
public string Name { get; set; }
}
public record Asd2(string Name);
public Task DoSomethingAsync<TInput>(TInput data) where TInput : class
{
var message = JsonSerializer.Serialize(data); // if TInput is a string, it results into faulty \u0022 codes
}
Edit: The actual issue is that I have JsonSerializer.Serialize(data) inside that method and if a string is passed accidentally, it will result in something like:
"{\u0022Name\u0022:\u0022Test\u0022}"
>Solution :
If your list of allowed types can’t be formulated with a type constraint, consider creating a list of allowed types (either hardcoded in code or with reflection at runtime e.g. on the namespace) and test against that list at runtime right at the beginning of the method (like you also test incoming parameters). Maybe something like this
private static readonly HashSet<Type> AllowedTypes = new HashSet<Type>
{
typeof(MyTypeA),
typeof(MyTypeB),
};
public Task DoSomethingAsync<TInput>(TInput data)
{
if(!AllowedTypes.Contains(typeof(TInput)))
throw new ArgumentException($"The type {typeof(TInput).Name} can' t be used here.");
// ...
}
While this doesn’t help you at compile time, at least it helps you at runtime.