[英]C#/F# interoperability: cannot use C# types in F# code
I have a Visual Studio solution with 3 projects named BaseCs, UseCs and UseFs (all .net core 3.1 libraries).我有一个 Visual Studio 解决方案,其中包含 3 个名为 BaseCs、UseCs 和 UseFs(所有 .net 核心 3.1 库)的项目。
//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>'
()
No problem with Use.cs. Use.cs 没问题。 However, the F# compiler refuses to accept the code, complaining that The type 'EntityImported' is not compatible with the type 'IAggregateEvent'但是,F# 编译器拒绝接受代码,抱怨“EntityImported”类型与“IAggregateEvent”类型不兼容
How do I get if F# UseFs.fs the same result as in C# UseCs.cs?如果 F# UseFs.fs 与 C# UseCs.cs 中的结果相同,我如何获得?
F# does not support covariance/contravariance like C# does. F# 不像 C# 那样支持协变/逆变。 There is an open issue about this here .有关于这一个开放的问题在这里。
Explicit (static) casting to IAggregateEvent<IIdentity>
does not work in your case because of this.因此,对IAggregateEvent<IIdentity>
显式(静态)转换在您的情况下不起作用。
All is not lost, however, since you can resort to dynamic upcast:然而,一切都没有丢失,因为您可以求助于动态向上转换:
let importEvent = new ImportEvent(unbox entityImported, null)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.