实现通用接口:构造导致代码比类型注释指示的更不通用

Implement generic interface: construct causes code to be less generic than indicated by the type annotations

我需要实现这样的接口:

interface IEvent<T> : IEvent {
  T Data { get; }
}
public interface IEvent
{
  Guid Id { get; set; }
  long Version { get; set; }
  long Sequence { get; set; }
  object Data { get; }
  Guid StreamId { get; set; }
  string StreamKey { get; set; }
  DateTimeOffset Timestamp { get; set; }
  string TenantId { get; set; }
  Type EventType { get; }
  string EventTypeName { get; set; }
  string DotNetTypeName { get; set; }
}

这就是我想出的:

type WrappedEvent<'T>(x: 'T) =
    interface Events.IEvent with
      member val Data = x with get
      member val DotNetTypeName = null with get, set
      member val EventType = null
      member val EventTypeName = null with get, set
      member val Id = Guid.Empty with get, set
      member val Sequence = int64 (0) with get, set
      member val StreamId = Guid.Empty with get, set
      member val StreamKey = null with get, set
      member val TenantId = null with get, set
      member val Timestamp = DateTimeOffset.MinValue with get, set
      member val Version = int64 (0) with get, set

WrappedEvent是这样使用的:

let MapToSubtype subtype =
    match subtype with
    | CustomerRegistered registeredCustomer -> WrappedEvent<CustomerRegisteredEvent> registeredCustomer :> Events.IEvent
    | CustomerDeleted deletedCustomer -> WrappedEvent<CustomerDeletedEvent> deletedCustomer :> Events.IEvent

编译器在 WrappedEvent<'T>

处为 <'T> 抛出错误
This type parameter has been used in a way that constrains it to always be 'obj'
This code is less generic than required by its annotations because the explicit type variable 'T' could not be generalized. 
It was constrained to be 'obj'.

Datamember val Data:

处显示警告
This construct causes code to be less generic than indicated by the type annotations. 
The type variable 'T has been constrained to be type 'obj'.

我该如何解决这个问题?

更新:

如果我像这样实现接口 interface Events.IEvent<'T> with(使用通用参数),我会收到此错误:

No implementation was given for 'Events.IEvent.get_Data() : obj'. 
Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.

首先,你在这里实现了两个接口,而不是一个,- IEvent<T>及其基础接口IEvent。因此,您需要添加两个 interface ... with 块 - 每个块一个:

type WrappedEvent<'T>(x: 'T) =
    interface Events.IEvent<'T> with
      member val Data = x with get

    interface Events.IEvent with
      member val Data = x with get
      member val DotNetTypeName = null with get, set
      member val EventType = null
      ...

Second,在实现IEvent接口时,注意其Data成员的类型:是obj。因此,如果您使用 x 初始化该成员,那么 x 必须具有类型 obj。这就是您最初错误的根源:x 的使用方式会使其限于 obj.

要解决此问题,您需要在使用它初始化 Data 之前将 x 向下转换为 obj

    interface Events.IEvent with
      member val Data = x :> obj with get

但是等等!这将仍然不起作用。问题是,member val 不仅声明了一个 属性,而且还为它声明了一个支持 字段 。现在您要声明两个不同的支持字段,都命名为 Data,但类型不同。 (另外,顺便说一句,您实际上不需要单独的支持字段,对吧?因为您已经有了 x

所以为了解决这个问题,让它们成为没有支持字段的属性:

    interface Events.IEvent<'T> with
        member self.Data with get() = x

    interface Events.IEvent with
        member self.Data with get() = x :> obj
        ...