簡體   English   中英

C#/F# 互操作性:不能在 F# 代碼中使用 C# 類型

[英]C#/F# interoperability: cannot use C# types in F# code

我有一個 Visual Studio 解決方案,其中包含 3 個名為 BaseCs、UseCs 和 UseFs(所有 .net 核心 3.1 庫)的項目。

  • BaseCs 在 C# 中,只有一個包含一系列類型定義的源文件 Definitions.cs
  • UseCs 在 C# 中只有一個源文件 Use.cs 包含一個簡單的類和一個方法,從 BaseCs 創建類型的實例
  • UseFs 是 UseCs 的 F# 版本
//Definitions.cs
using System;

namespace BaseCs
{
    public interface IIdentity
    {
        string Value { get; }

        Guid GetGuid();
    }

    public abstract class Identity<T> : IIdentity where T : Identity<T>
    {
        public string Value { get; }

        public Guid GetGuid()
        {
            throw new NotImplementedException();
        }
    }

    public class EntityId : Identity<EntityId> { }

    public interface IMessage
    {
        string SourceId { get; }
    }

    public interface IAggregateEvent : IMessage { }

    public interface IAggregateEvent<out TIdentity> : IAggregateEvent
        where TIdentity : IIdentity
    {
        TIdentity Id { get; }
    }

    public interface IAggregateEvent<out TIdentity, out TData> : IAggregateEvent<TIdentity>
        where TIdentity : IIdentity
    {
        TData Data { get; }
    }


    public abstract class AggregateEvent<TIdentity, TData> : IAggregateEvent<TIdentity, TData> where TIdentity : IIdentity
    {
        protected AggregateEvent(TIdentity id, TData data, string sourceId)
        {
            this.Id = id;
            this.Data = data;
            this.SourceId = sourceId;
        }

        public TData Data { get; }
        public TIdentity Id { get; }
        public string SourceId { get; }
    }

    public interface IAuditedAggregateEvent : IAggregateEvent
    {
        EntityId EntityId { get; set; }

        string EntitySortName { get; set; }
    }

    public interface IAuditedAggregateEvent<out TIdentity, out TData> : IAuditedAggregateEvent, IAggregateEvent<TIdentity, TData>
        where TIdentity : IIdentity
    {
    }

    public abstract class AuditedAggregateEvent<TIdentity, TData> : AggregateEvent<TIdentity, TData>, IAuditedAggregateEvent<TIdentity, TData> where TIdentity : IIdentity
    {
        public AuditedAggregateEvent(TIdentity id, TData data, string sourceId) : base(id, data, sourceId)
        { }

        public EntityId EntityId { get; set; }
        public string EntitySortName { get; set; }
    }

    public interface ISimpleAudit
    {
        EntityId CreatedBy { get; set; }
        string CreatedBySortName { get; set; }
        DateTimeOffset CreatedOn { get; set; }
        EntityId UpdatedBy { get; set; }
        string UpdatedBySortName { get; set; }
        DateTimeOffset UpdatedOn { get; set; }
    }

    public partial class EntityData : ICloneable, ISimpleAudit
    {
        public object Clone()
        {
            throw new NotImplementedException();
        }

        public EntityId CreatedBy { get; set; }
        public string CreatedBySortName { get; set; }
        public DateTimeOffset CreatedOn { get; set; }
        public EntityId UpdatedBy { get; set; }
        public string UpdatedBySortName { get; set; }
        public DateTimeOffset UpdatedOn { get; set; }
    }

    public interface IProtocol { }

    public interface IAccountingServiceProtocol : IProtocol { }

    public interface IEntityProtocol : IProtocol, IAccountingServiceProtocol { }

    public interface IDataImportEvent
    {
    }

    public interface IUnorderedEvent { }

    public class EntityImported : AuditedAggregateEvent<EntityId, EntityData>, IEntityProtocol, IDataImportEvent, IUnorderedEvent
    {
        public EntityImported(EntityId id, EntityData data, string sourceId) : base(id, data, sourceId) { }
    }
    public interface ICommandId
    {
        Guid CommandId { get; }
    }

    public interface ICommand : IMessage, ICommandId
    { }
    public interface IImportProtocol { }

    public class ImportEvent : ICommand, IImportProtocol
    {
        public ImportEvent(IAggregateEvent<IIdentity> @event, string sourceId)
        {
            Event = @event;
            SourceId = sourceId;
        }

        public static ImportEvent Of(IAggregateEvent<IIdentity> evt, string sourceId = null) => new ImportEvent(evt, sourceId);
        public string SourceId { get; }
        public Guid CommandId { get; }
        public IAggregateEvent<IIdentity> Event { get; private set; }
    }
}

//UseCs.cs
using BaseCs;
using System;

namespace UseCs
{
    public class UseCs
    {
        void method()
        {
            var entityImported = new EntityImported(null, null, Guid.NewGuid().ToString());
            var importEvent = new ImportEvent(entityImported, null);
        }
    }
}
//UseFs.fs
namespace UseFs

open BaseCs
open System

module UseFs =
    let method() =
        let entityImported = new EntityImported(null, null, Guid.NewGuid().ToString());
        let importEvent = new ImportEvent(entityImported, null); //compiler error: The type 'EntityImported' is not compatible with the type 'IAggregateEvent<IIdentity>'
        ()        

Use.cs 沒問題。 但是,F# 編譯器拒絕接受代碼,抱怨“EntityImported”類型與“IAggregateEvent”類型不兼容

在此處輸入圖片說明

如果 F# UseFs.fs 與 C# UseCs.cs 中的結果相同,我如何獲得?

F# 不像 C# 那樣支持協變/逆變。 有關於這一個開放的問題在這里

因此,對IAggregateEvent<IIdentity>顯式(靜態)轉換在您的情況下不起作用。

然而,一切都沒有丟失,因為您可以求助於動態向上轉換:

let importEvent = new ImportEvent(unbox entityImported, null)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM