仅限制 DTO 模型的通用方法(class & 记录)

Restrict generic method for DTO models only (class & record)

非常简单的问题。我只想在输入中允许 DTO 模型(class 和记录类型)。

如果我只保留 class 约束,我仍然可以将 string 放在那里。我不想允许原始类型。

如果我输入 class, new(),它不允许 string 正如预期的那样,但我也不允许使用位置记录,这是一个问题。

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:实际问题是我在该方法中有 JsonSerializer.Serialize(data),如果 string 被意外传递,它会导致类似:

"{\u0022Name\u0022:\u0022Test\u0022}"

您需要对限制具有某种共性。 这需要是公共基础 class 或接口。

既然你也想用Records,那么这肯定是一个接口。但是如果您只是为了这个目的,您可以只定义一个简单的空的。

所以你定义了一个简单的空接口(如果你真的有一些通用的更好functions/properties)。

public interface MyInterface
{

}

所以你的代码看起来像这样

public Task DoSomethingAsync<TInput>(TInput data) where TInput : MyInterface
{
}

你所有的 classes 和记录都是这样继承的。

public record AsdRecord: MyInterface
{
       //details here
}

public class AsdClass: MyInterface
{
        //details here
}

如果您的允许类型列表不能用类型约束来制定,请考虑创建一个允许类型列表(在代码中硬编码或在运行时使用反射,例如在命名空间上)并在运行时针对该列表进行测试就在方法的开头(就像您还测试传入参数一样)。也许是这样的

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.");

    // ...
}

虽然这在编译时对您没有帮助,但至少在运行时对您有帮助。