简体   繁体   English

C# 多级 Generics 具有继承/多态性

[英]C# Multi Level Generics with inheritance/polymorphism

I've been stumped on this for a while now but wanted to know if it was possible via another approach or I'm just missing a step.我已经为此困惑了一段时间,但想知道是否可以通过另一种方法实现,或者我只是错过了一步。

Here are the base classes.这是基类。

public class StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{}

public class StartType1 {}

public class StartType2 {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

I want to create a holder/container class to hold an array of my EndType0 class which will be used in Unity to draw a generic custom property drawer for my StartType0 class.我想创建一个持有人/容器 class 来保存我的 EndType0 class 的数组,它将在 Unity 中用于为我的 StartType0 class 绘制一个通用自定义属性抽屉。

Any suggestions or pointers in the right direction would be amazing as I've tried tackling this issue several times over the past few months.任何正确方向的建议或指示都会很棒,因为在过去的几个月里我已经多次尝试解决这个问题。

I thought I could try providing every parameter but I can't convert the StartType0 to my EndType0.我想我可以尝试提供每个参数,但我无法将 StartType0 转换为我的 EndType0。

public class TypeContainer<T0, T1, T2>
    where T0 : StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<StartType0<EndType1, EndType2>, EndType1, EndType2> container = new TypeContainer<StartType0<EndType1, EndType2>, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = (EndType0)container.array[0];
    }
}

I thought I could try providing EndType0 to the StartType0 parameter but I'm guessing it has issues due to not taking polymorphism into account.我想我可以尝试为 StartType0 参数提供 EndType0,但我猜它有问题,因为没有考虑多态性。

public class TypeContainer<T0, T1, T2>
    where T0 : StartType0<T1, T2>
    where T1 : StartType1
    where T2 : StartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

I would ideally love to approach it something like this way with some yummy polymorphism involved.理想情况下,我会喜欢以这种方式处理它,并涉及一些美味的多态性。

public class TypeContainer<T>
    where T : StartType0<StartType1, StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0> container = new TypeContainer<EndType0>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

-EDIT 1- -编辑1-

After following @JohnathanBarclay's comment I manage to make the following.在关注@JohnathanBarclay 的评论后,我设法做出以下决定。

public class StartType0<out T1, out T2>
    where T1 : StartType1, IStartType1
    where T2 : StartType2, IStartType2
{}

public interface IStartType1 {}

public class StartType1 : IStartType1 {}

public interface IStartType2 {}

public class StartType2 : IStartType2 {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

which then allows me to do the following and complete a compile.然后允许我执行以下操作并完成编译。

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1
    where T2 : IStartType2
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

This has issues being drawn into the unity editor though.不过,这在统一编辑器中存在问题。

-EDIT 2- -编辑2-

After some play around I found my current ideal setup so far经过一番尝试后,我找到了目前最理想的设置

public interface IStartType0<out T1, out T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public class StartType0<T1, T2>
    IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public interface IStartType1<out T> where T StartType1 {}

public class StartType1 : IStartType1<StartType1> {}

public interface IStartType2<out T> where T StartType2 {}

public class StartType2 : IStartType2<StartType2> {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

Having the 'more or less' guaranteed base types I am able to run my CustomPropertyDrawer over these and generate custom inspectors and even utilise 'Activator' for messing with the generic types.有了“或多或少”有保证的基本类型,我就可以在这些基础类型上运行我的 CustomPropertyDrawer 并生成自定义检查器,甚至可以利用“Activator”来处理通用类型。

After some play around with variance in generics I found my current ideal setup so far 在 generics 中尝试了一些变化之后,我发现目前为止我的理想设置

public interface IStartType0<out T1, out T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public class StartType0<T1, T2>
    IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{}

public interface IStartType1<out T> where T StartType1 {}

public class StartType1 : IStartType1<StartType1> {}

public interface IStartType2<out T> where T StartType2 {}

public class StartType2 : IStartType2<StartType2> {}

public class EndType0 : StartType0<EndType1, EndType2> {}

public class EndType1 : StartType1 {}

public class EndType2 : StartType2 {}

public class TypeContainer<T0, T1, T2>
    where T0 : IStartType0<T1, T2>
    where T1 : IStartType1<StartType1>
    where T2 : IStartType2<StartType2>
{
    public T0[] array = new T0[1];

    public TypeContainer()
    {
        array[0] = Activator.CreateInstance(typeof(T0));
    }
}

public class Tester
{
    public TypeContainer<EndType0, EndType1, EndType2> container = new TypeContainer<EndType0, EndType1, EndType2>();

    public Tester()
    {
        EndType0 instance = container.array[0];
    }
}

Having the 'more or less' guaranteed base types I am able to run my CustomPropertyDrawer over these and generate custom inspectors and even utilise 'Activator' for messing with the generic types.有了“或多或少”有保证的基本类型,我就可以在这些基础类型上运行我的 CustomPropertyDrawer 并生成自定义检查器,甚至可以利用“Activator”来处理通用类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM