在设计时动态返回接口

时间:2013-02-26 20:57:47

标签: c# dynamic fluent-interface

我正在尝试编写一个流畅的界面,该界面能够在设计时检测作为Linq Expression传递的属性类型,并根据对该类型的评估返回一个接口。

例如:

public class Searchable<Person>
{
    public Searchable()
    {
        CanSearch(x => x.Name)
            .Include(StringOperations.Contains);

        CanSearch(x => x.Age)
            .Exclude(NumericOperators.GreaterThan);
    }
}

在CanSearchMethod中,我希望能够做到这样的事情:

public IOperations CanSearch(Expression<Func<T, object>> expression)
{
    var type = (/* Code to pick apart expression */); 

    if(type == typeof(int))
        return new ClassImplementingINumericOperations();
    if(type == typeof(string))
        return new ClassImplementingIStringOperations();
    if(type == typeof(IEnumerable))
        return new ClassImplementingIIEnumerableOperations();

    return null;
}

不同接口的Include和Exclude方法的区别仅在于作为参数接受的枚举:

public interface IOperations
{
}

public interface INumericOperations : IOperations
{
    INumericOperations Include(NumericOperationsEnum op);
    INumericOperations Exclude(NumericOperationsEnum op);
}

public interface IStringOperations : IOperations
{
    IStringOperations Include(StringOperationsEnum op);
    IStringOperations Exclude(StringOperationsEnum op);
}

public interface IIEnumerableOperations : IOperations
{
    IIEnumerableOperations Include(CollectionOperationsEnum op);
    IIEnumerableOperations Exclude(CollectionOperationsEnum op);
}

我怀疑这是不可能的,但我完全不能完全理解,因为动力学可以做一些时髦的魔术。

我已经查看了其他一些流畅的接口,但似乎没有人评估表达式,以确定在设计时要返回的类型。

2 个答案:

答案 0 :(得分:1)

您可以使用重载编译时类型安全来执行此操作:

public IStringOperations CanSearch<T>(Expression<Func<T, string>> expression);
public IIEnumerableOperations<TItem> CanSearch<T, TItem>(Expression<Func<T, IEnumerable<TItem>> expression);

但是,对于数字类型,您需要为7种数字类型中的每一种都需要单独的重载,或者需要一种非常不灵活的通用INumericOperations<TNumber>

答案 1 :(得分:1)

您可以利用重载和类型推断。像这样:

IStringOperations CanSearch(
    Expression<Func<T, string>> expression)
{ /* ... */ }

INumericOperations CanSearch<TCompare>(
    Expression<Func<T, TCompare>> expression)
    where TCompare : IComparable<TCompare>
{ /* ... */ }

IIEnumerableOperations CanSearch<TSeq>(
    Expression<Func<T, IEnumerable<TSeq>>> expression)
{ /* ... */ }

现在,CanSearch(x => x.Name)将返回IStringOperations,而CanSearch(x => x.Age)将返回INumericOperations个对象。