【问题标题】:C# Generic Type Inference With Multiple Types具有多种类型的 C# 泛型类型推断
【发布时间】:2012-05-23 12:05:56
【问题描述】:

我有以下通用方法将一种类型的输入对象序列化为超类型,如下所示:

public string SerialiseAs<TResult, TInput>(TInput input) where TInput : TResult
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TResult));
    MemoryStream stream = new MemoryStream();
    ser.WriteObject(stream, input);
    stream.Position = 0;
    StreamReader reader = new StreamReader(stream);
    return reader.ReadToEnd();
}

我必须调用这个方法指定两个泛型类型如下:

MySubType x = new MySubType();
string json = SerialiseAs<MySuperType, MySubType>(x);

我的问题是,为什么在这种情况下不能推断出TInput?是因为TResult 实际上没有用作返回类型吗?以下代码更简洁,但由于缺少输入类型而无法编译:

MySubType x = new MySubType();
string json = SerialiseAs<MySuperType>(x);

【问题讨论】:

  • C++ 多吗?如果只有 C# 有(成员)类型定义。我想要那个。但是不,那样不行。

标签: c# .net generics


【解决方案1】:

我的问题是,为什么在这种情况下不能推断出 TInput?

可以——它是TResult,无法推断,也无法指定“部分”推断。

可以有时将类型参数分为通用类型和通用方法的类型参数,所以你' d 最终得到:

// Explicitly state TResult, and infer TInput
Serializer<MySuperType>.Serialize(x);

【讨论】:

  • 这更有意义。我喜欢在类级别指定输出类型但推断输入类型的想法。然后我仍然可以对通用Serialise 方法进行继承检查。我也可以尝试使用像Serialise(x).As&lt;MySuperType&gt;() 这样的流利语法,但这对于我实际使用它的目的可能有点复杂。
  • @AdamRodger:那样会很棘手,因为当您指定TResult second 时,您不能强加TInput : TResult 约束。如果您不介意失去编译时约束,那当然不是问题。
  • 标记为答案,实际原因是您不能部分指定泛型类型。
【解决方案2】:

为什么不直接写成这样:

public string SerialiseAs<TResult>(TResult input)
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TResult));
    MemoryStream stream = new MemoryStream();
    ser.WriteObject(stream, input);
    stream.Position = 0;
    StreamReader reader = new StreamReader(stream);
    return reader.ReadToEnd();
}

由于TInput 派生自TResult,因此您根本不需要指定。

【讨论】:

  • 这不适用于DataContractJsonSerialiser,因此我将方法更改为采用两种类型。当您将实例作为MySuperClass 传递时,MySubType 中的任何额外属性都会从序列化结果中省略。您也没有在输出中获得我需要的 __type 属性。您必须将您的实例作为子类型传递,但告诉它作为超类型序列化。
  • @AdamRodger - 这很奇怪。我看不出DataContractJsonSerializer 如何确定您传递给它的变量的类型。 WriteObject() 方法将一个简单的object 作为其参数。你确定吗?
  • 是的,绝对确定。我还有一个Serialise 方法,它不像上述方法那样进行类型改组,并且使用相同的输入它们都会产生不同的输出。缺少 __type 属性。
  • @AdamRodger - 对我来说就像一个魅力:http://pastebin.com/4gTfrvuy 你是否正在使用已知类型或其他东西做一些魔法?我对 WCF 不太熟悉,但它要求我将这个奇怪的 KnownType 属性放在类 A 上,然后它才能工作。它还在异常消息中提到了DataContractResolver
  • 是的,MySuperType 是一个抽象类,有许多实现子类(通过KnownType 指定)。您需要自动添加 __type 属性,以便您可以在客户端反序列化。我不认为特定的细节很重要,因为我有一个工作方法,只是对为什么我无法推断输入类型感兴趣。无论如何,这只是在我的单元测试中使用的一个小辅助方法,因此我可以检查是否存在必需的属性,并且省略了非必需的默认属性等。
猜你喜欢
  • 2020-06-24
  • 2013-03-04
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多