【问题标题】:Return a generic type of another generic type返回另一个泛型类型的泛型类型
【发布时间】:2021-12-25 12:29:27
【问题描述】:

我有一个自定义枚举类:

public abstract class Enum<T> where T : struct, IComparable
{
    public T Id { get; }

    public string Value { get; }
    
    protected Enum(T id, string @value)
    {
        Id = id;
        Value = @value;
    }
}

还有一个继承自这个类的类:

public sealed class Status : Enum<byte>
{
    public static readonly Status Pending = new Status(0, "PENDING");
    public static readonly Status Finished = new Status(1, "FINISHED");
    
    private Status(byte id, string name) : base(id, name)
    {
    }
    
    public static Status Create (string @value)
    {
        // some logic here
        //return Wrapper.Wrap(Finished);
        return Finished;
    }
    
    public static Wrapper<Status> CreateWrapper(string @value)
    {
        // some logic here
        return Wrapper.Wrap(Finished);
    }
}

现在我想在 AutoMapper 中制作一个自定义类型转换器,以下这些转换器可以正常工作:

public class StatusConverter<TType> : ITypeConverter<string, Enum<byte>>
{
    public Enum<byte> Convert(string source, Enum<byte> destination, ResolutionContext context)
    {
        return Status.Create(source);
    }
}

public class StatusConverter2<TValue> : ITypeConverter<string, Wrapper<Status>> // works fine
{
    public Wrapper<Status> Convert(string source, Wrapper<Status> destination, ResolutionContext context)
    {
        return Status.CreateWrapper(source);
    }
}

现在我创建了一个新的 Wrapper 类:

public class Wrapper
{
    public static Wrapper<T> Wrap<T>(T @value)
    {
        return new Wrapper<T>(@value);
    }
}

public class Wrapper<T>
{
    T Value;
    
    internal Wrapper(T @value)
    {
        Value = @value;
    }
}

我想做以下事情:

public class StatusConverter3<TValue> : ITypeConverter<string, Wrapper<Enum<byte>>> // doesn't work with Enum<T>
{
    public Wrapper<Enum<byte>> Convert(string source, Wrapper<Enum<byte>> destination, ResolutionContext context)
    {
        return Status.CreateWrapper(source);
    }
}

我想创建一个泛型类型转换器,但我收到一个错误,我无法将 Wrapper&lt;Status&gt; 隐式转换为 Wrapper&lt;Enum&lt;byte&gt;&gt;

这是我的问题的 dotnetfiddle 演示: https://dotnetfiddle.net/xM9JVg

【问题讨论】:

    标签: c# generics inheritance automapper


    【解决方案1】:

    你应该使用Covariant generic modifier

    1. 介绍一个界面

      public interface IWrapper<out T> 
      { 
      }
      
    2. 在你的 Wrapper 上实现它

      Wrapper<T> : IWrapper<T>
      
    3. 在转换器中使用接口而不是类

      public class StatusConverter3<TValue> : ITypeConverter<string, IWrapper<Enum<byte>>> 
      

    请注意,在这种情况下,您的 Wrapper&lt;T&gt; 不允许使用将 T 作为输入参数的方法

    查看fork

    【讨论】:

    • 该死,这很聪明。我通常会从 IDE 获得建议,在我的界面中使用 inout,但我从未真正理解它们的用途。这个挑战让我更了解它。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-08-02
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多