我正在开始研究名为Sieve.NET的小OSS库.
签名允许某人定义Sieve,如下所示:
new EqualitySieve<ABusinessObject>().ForProperty(x => x.AnInt);
这实际上返回了Sieve< ABusinessObject,int>,但我已尽力确保用户不必过多关心该部分.
任务
我想找到一种方法来设置一个接口,我根本不关心属性类型 – 只是它始终是一致的.
基本上,我希望能够声明一个ISieve< TFilterObjectType>,并且能够让该接口定义如下:
ISieve<TFilterObjectType,TTypeIDontCareAbout> ForValue(TTypeIDontCareAbout);
我的目标是能够拥有一个由ISieve< ABusinessObject>组成的课程.而不是ISieve< ABusinessObject,int>.
题
>接口是否有办法声明一种实际上是通配符的类型,并说“我不关心这是什么类型,只是它是一致的?”
我最初的研究表明没有,但我希望被证明是错的.
更新&澄清
我真正想弄清楚的是:
>我允许用户创建EqualitySieve< ABusinessObject>().ForProperty(x => x.AnInt).
>这实际上返回了EqualitySieve< ABusinessObject,int>对于用户来说,但由于它是一个流畅的界面,我将它们从必须关心那个部分中移除.
>我希望EqualitySieve,LessThanSieve等实施ISieve< ABusinessObject>.
>我希望ISieve< ABusinessObject强制执行一项合同,我可以允许某人调用ForValues()并期望它返回带有更新值的ISieve.
>然而,此时,EqualitySieve< ABusinessObject>实际上是EqualitySieve< ABusinessObject,int>.但我并不特别关心那时的房产类型.
>基本上,因为我正在抽象出EqualitySieve< ABusinessObject,int>部分,我还想看看我是否可以通过界面引用对象时抽象出来.
>长期计划是我想要一个SieveLocator,其中类可以实现IFindableSieve< ABusinessObject>理想情况下,它将返回ISieve< ABusinessObject>.然后我的目标是能够找到给定对象的Sieves.
>所以我认为这可能是我设计的限制,我将不得不寻找其他方法.对此提出的任何建议或对我可能没有看到的模式的引用也会有所帮助.
解决方法
interface I<T> { //The generic type parameter U is independent of T. //Notice how F "forwards" the type U from input to output. Tuple<T,U> F<U>(U u); }
考虑以下玩具类:
class C : I<char> { public char Value { get; set; } public Tuple<char,U> F<U>(U u) { return Tuple.Create(Value,u); } }
以下是一些示例用法:
I<char> instance = new C { Value = '!' }; Tuple<char,int> x = instance.F(5); // ('!',5) Tuple<char,string> y = instance.F("apple"); // ('!',"apple")
更新
- I allow users to create an
EqualitySieve<ABusinessObject>().ForProperty(x=>x.AnInt)
.- This actually returns an
EqualitySieve<ABusinessObject,int>
to the user,but since it’s a fluent interface I remove them from having to care about that part.- I would like
EqualitySieve
,LessThanSieve
,etc. to implementISieve<ABusinessObject>
.
使用我上面提到的想法,你可以做你想要的(我想).
interface ISieve<T> { //It's still not clear what you actually want in this interface... } static class Sieve { public EqualitySieve<T> Equality<T>() { return new EqualitySieve<T>(); } public LessThanSieve<T> LessThan<T>() { ... } } class EqualitySieve<T> : ISieve<T> { //Notice how the property type P is independent of T //and can be inferred here from the passed expression public EqualitySieve<T,P> ForProperty<P>( Expression<Func<T,P>> propertyExpression) { return new EqualitySieve<T,P> { PropertyExpression = propertyExpression }; } } class EqualitySieve<T,P> : ISieve<T> { public Expression<Func<T,P>> PropertyExpression { get; set; } }
用法:
//Assuming MyObject.MyProperty is an int property //s has type EqualitySieve<MyObject,int> var s = Sieve.Equality<MyObject>().ForProperty(x => x.MyProperty);