模拟多态/通用枚举 - C# [英] Simulating Polymorphic/Generic Enumerations - C#

查看:104
本文介绍了模拟多态/通用枚举 - C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这是一个奇怪的标题,而且我知道枚举不可能继承,所以让我解释一下.

I know it's a bizarre title, and i know inheritance is not possible with enums, so let me explain.

如果我有以下课程:

  • 水果(摘要)
    • 苹果(混凝土 - 源自水果)
    • 橙色(混凝土 - 源自水果)

    我有以下方法,用泛型实现:

    And i have the following method, implemented with generics:

    public ICollection<T> FindFruit<T>() where T : Fruit
    {
       return _fruitRepository
                 .Fruits
                 .OfType<T>()
                 .ToList();
    }
    

    我是这样使用的:

    var apples = _fruitServices.FindFruit<Apple>();
    

    一切正常.

    现在 - 我目前有以下枚举:

    Now - i currently have the following enum:

    public enum FruitAssociations
    {
       Color,
       Manufacturers
    }
    

    基本上,一个水果"可以有很多关联,它指定要包含在我的存储库结果中的关联.

    Basically a "Fruit" can have many associations, which designates what associations to include in the result from my repository.

    所以上面的FindFruit方法其实是这样的:

    So the FindFruit method above is actually like this:

    public ICollection<T> FindFruit<T>(FruitAssociations[] assocs) where T : Fruit
    {
       return _fruitRepository
                 .Fruits
                 .OfType<T>()
                 .IncludeAssocs(assocs) // ObjectQuery<Fruit> extension method.
                 .ToList();
    }
    

    这是扩展方法:

    public static ObjectQuery<Fruit> IncludeAssocs(this ObjectQuery<Fruit> source, FruitAssociations[] assocs)
    {
       if (assocs.Contains(FruitAssociations.Color))
          query = query.Include("Color");
       // etc      
    }
    

    也工作正常.然而,我现在面临的问题是我对特定水果有关联.

    Also works fine. The problem i am now facing however is i have associations on particular Fruit.

    例如

    public enum OrangeAssociations
    {
       OrangeFamilies
    }
    

    而且我不确定如何拥有一个能够根据 T 的类型返回关联的 FindFruit 方法.

    And i'm not sure how to have a single FindFruit method that is capable of returning associations based on the type of T.

    这是我希望能够做到的最终结果:

    var oranges = _fruitServices.FindFruit<Orange>(new[] { OrangeAssociations.OrangeFamilies });
    var apples = _fruitServices.FindFruit<Apple>(new[] { AppleAssociations.AppleFamilies });
    

    但是如果没有为每种水果类型设置单独的 FindFruit 方法,我无法弄清楚如何做到这一点,因此无法解决通用 T 类型参数的问题.

    But i can't figure out how to do that without having seperate FindFruit methods for each fruit type, and hence defeating the point of the generic T type parameter.

    对于那些对我在这里做什么感到好奇的人 - 我正在使用 Entity Framework 4 的预先加载,因此使用 .Include 方法(它需要一个字符串来指定导航财产).因此,我的服务接受给定实体的枚举数组,然后我使用扩展方法将其转换为 .Include 语句中使用的字符串.

    For those who are curious as to what i'm doing here - i'm using eager loading with Entity Framework 4, and therefore using the .Include method (which takes a string designating the navigational property). So my service accepts an array of enumerations for a given entity, then i use an extension method to translate that to a string used in the .Include statement.

    我认为解决方案不是接受枚举数组,而是接受泛型类:

    I'm thinking the solution is to instead of accepting an array of enums, accept a generic class:

    public ICollection<T> FindFruit<T>(FruitAssociations<T> assocs) where T : Fruit
    

    像这样使用它:

    var associations = new FruitAssociations<Orange>(OrangeAssociations.OrangeFamilies);
    var apples = _fruitServices.FindFruit<Apple>(associations);
    

    但我不确定这将如何运作,或如何实施.

    But i'm not sure how that would work, or how to implement it.

    希望我的问题有意义并且不会太长/太复杂.

    Hopefully my question makes sense and is not too long/complicated.

    推荐答案

    Eric Lippert 会来我家用棍子打我,但它管用.

    Eric Lippert will come to my house and beat me with a stick for this, but it works.

    用法:

    // finds fruits of type Orange, includes Color and OrangeFamilies
    var result = FindFruit(OrangeAssociation.Color,
                           OrangeAssociation.OrangeFamilies);
    

    // finds fruits of type Fruit, includes Manufacturers
    var result = FindFruit(FruitAssociation.Manufacturers);
    

    <小时>

    实施:

    static ICollection<TFruit> FindFruit<TAssoc, TFruit>(
        params FruitAssociation<TAssoc, TFruit>[] assocs)
        where TAssoc : FruitAssociation<TAssoc, TFruit>, new()
        where TFruit : Fruit
    {
        var query = _fruitRepository.Fruits.OfType<TFruit>();
    
        foreach (var assoc in assocs)
        {
            query = query.Include(assoc.Name);
        }
    
        return query.ToList();
    }
    

    abstract class FruitAssociation<TAssoc, TFruit>
        where TAssoc : FruitAssociation<TAssoc, TFruit>, new()
        where TFruit : Fruit
    {
        public static readonly TAssoc Color = Define("Color");
    
        public static readonly TAssoc Manufacturers = Define("Manufacturers");
    
        protected static TAssoc Define(string name)
        {
            return new TAssoc { Name = name };
        }
    
        public string Name
        {
            get;
            private set;
        }
    }
    
    sealed class FruitAssociation : FruitAssociation<FruitAssociation, Fruit>
    {
    }
    
    sealed class OrangeAssociation : FruitAssociation<OrangeAssociation, Orange>
    {
        public static readonly OrangeAssociation OrangeFamilies =
            Define("OrangeFamilies");
    }
    

    这篇关于模拟多态/通用枚举 - C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆