0

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

例如:

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);
}

我怀疑这是不可能的,但我不能完全解决,因为动态可以做一些时髦的魔法。

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

4

2 回答 2

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>,这会令人讨厌地不灵活。

于 2013-02-26T21:11:00.480 回答
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)将返回一个IStringOperationswhileCanSearch(x => x.Age)将返回一个INumericOperations对象。

于 2013-02-26T21:12:19.983 回答