如何在不使用子接口或显式类的情况下组合接口

时间:2016-12-13 14:26:23

标签: c# interface

我试图找出一种直接的方法来组合接口而不创建新的子接口,因为接口具有多维关系。

interface IAnimal {}

interface ISwimmingAnimal : IAnimal {}

interface IVertebrate : IAnimal {}

interface IMammal : IVertebrate
{
    IMammal Process();
}

interface IInvertebrate : IAnimal {}

interface IMollusc : IInvertebrate
{
    IMollusc Process(object data);
}

因此,一些具体的类将是

class Vertebrate : IVertebrate {}

class SwimmingInvertebrate : ISwimmingAnimal, IInvertebrate {}

class SwimmingMammal : ISwimmingAnimal, IMammal
{
    IMammal Process();
}

无需合成界面,例如ISwimmingAnimalInvertebrateISwimmingAnimalMammal

一切顺利,直到我需要使用包含某些组合类型实例的类/接口(理论上我想要的):

interface IAnimalsCollection
{
    IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
    {IAnimal, IVertebrate} Vertebrate { get; }
    IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; }

    void UpdateVertebrate({IAnimal, IVertebrate} vertebrate);
    void UpdateInvertebrate({IAnimal, IInvertebrate} invertebrate, int index);
}

class SwimmingAnimalsCollection : IAnimalsCollection
{
    public IEnumerable<ISwimmingAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
    public {ISwimmingAnimal, IMammal} Vertebrate { get; }
    public IEnumerable<{ISwimmingAnimal, IMollusc}> Invertebrates { get; }

    public void UpdateVertebrate({ISwimmingAnimal, IMammal} vertebrate);
    public void UpdateInvertebrate({ISwimmingAnimal, IMollusc} invertebrate, int index);
}

我试过这个

interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal : IAnimal
    where TVertebrate : TAnimal, IVertebrate
    where TInvertebrate : TAnimal, IInvertebrate
{
    IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
    {IAnimal, IVertebrate} Vertebrate { get; }
    IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; }

    void UpdateVertebrate(TVertebrate vertebrate);
    void UpdateInvertebrate(TInvertebrate invertebrate, int index);
}

class SwimmingAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : AnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal : ISwimmingAnimal
    where TVertebrate : TAnimal, IMammal
    where TInvertebrate : TAnimal, IMollusc
{
    public IEnumerable<TAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates
    public TVertebrate Vertebrate { get; }
    public IEnumerable<TInvertebrate> Invertebrates { get; }

    public void UpdateVertebrate(TVertebrate vertebrate) {}
    public void UpdateInvertebrate(TInvertebrate invertebrate, int index) {}
}

除了我找不到用接口实例化SwimmingAnimalsCollection的方法,因为这是我试图首先解决的问题,我也不能使用{{1}的类实现}和IMammal可能会返回完全不同的类。 实际上,在实际实现中,有一对IMollusc的类将返回一个UnProcessedX类,如果你试图进一步处理它,它将自动返回。

因为我想做

ProcessedX

collection.UpdateVertebrate((TVertebrate)collection.Vertebrate.Process()) 不是ProcessedVertebrate

我认为大致有三种方法可以解决这个问题:

  • 我可以分解并创建组合接口,杀死任何 简单的依赖注入。
  • 我可以创建虚拟抽象基类(希望没有什么需要 深度继承链),杀死任何依赖的可能性 注射。
  • 或者我可以用魔杖击败C#编译器,直到它消失 并允许就地界面组合。

1 个答案:

答案 0 :(得分:1)

我认为最接近你想要的是以下设置:

public interface IAnimal { }
public interface IVertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { }
public interface IInvertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { }
public interface ISwimmingAnimal : IAnimal { }
public interface ISwimmingVertebrate : IVertebrate<ISwimmingAnimal> { }
public interface ISwimmingInvertebrate : IInvertebrate<ISwimmingAnimal> { }

请注意,您仍在创建接口之间的依赖关系。现在你的收藏品看起来像这样:

public interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal: IAnimal
    where TVertebrate: IVertebrate<TAnimal>
    where TInvertebrate: IInvertebrate<TAnimal>
{
    IEnumerable<IAnimal> Animals { get; }
    IEnumerable<TVertebrate> Vertebrates { get; }
    IEnumerable<TInvertebrate> Invertebrates { get; }
    ....
}

public class AnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal : IAnimal
    where TVertebrate : IVertebrate<TAnimal>
    where TInvertebrate : IInvertebrate<TAnimal>
{
    public AnimalsCollection(IEnumerable<TVertebrate> vertebrates, IEnumerable<TInvertebrate> invertebrates)
    {
        Vertebrates = vertebrates;
        Invertebrates = invertebrates;
    }

    public IEnumerable<IAnimal> Animals => Vertebrates.Cast<IAnimal>().Concat(Invertebrates.Cast<IAnimal>());     
    public IEnumerable<TInvertebrate> Invertebrates { get; }
    public IEnumerable<TVertebrate> Vertebrates { get; }
}

一些具体类型:

public abstract class SwimmingAnimal: ISwimmingAnimal { }
public class JellyFish: IInvertebrate<SwimmingAnimal> { }
public class Fish: IVertebrate<SwimmingAnimal> { }

现在,您只能使用接口实例化具体集合:

var swimmingCollection = new AnimalsCollection<ISwimmingAnimal, IVertebrate<ISwimmingAnimal>, IInvertebrate<ISwimmingAnimal>>(Enumerable.Empty<Fish>(), Enumerable.Empty<JellyFish>());