模拟多态/通用枚举 - C# [英] Simulating Polymorphic/Generic Enumerations - 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屋!