【问题标题】:Interface for both Value and Reference types in a Generic泛型中值和引用类型的接口
【发布时间】:2012-08-25 04:08:39
【问题描述】:

我正在创建一个接口,该接口将由将用作过滤器以创建查询字符串的类实现。每个过滤器将负责在查询中构造一个参数。用户可以定义是否包含运算符以及运算符应该是什么以及值。值的表达方式取决于数据类型。

布尔值:“=0”

整数: " >= 2"

日期时间:“'2012-01-10'”

字符串: " = '一些字符串'"

public interface IFilter<T> 
{
    Nullable<T> Value { get; set; }
    String Operator { get; set; }
    Boolean IncludeOperator { get; set; }
}

这个接口将由一个抽象类实现,该类定义基本字段、属性并覆盖 ToString 方法;以及一个抽象的 GetValueAsString() 方法,应该重写该方法以执行从过滤器构造适当字符串所需的任何逻辑。

public abstract class Filter<T> : IFilter<T> 
{
    Nullable<T> _value;
    String _operator = "=";
    Boolean _includeOperator = false;

    public Nullable<T> Value { get { return this._value; } set { this._value = value; } }

    public String Operator { get { return this._operator; } set { this._operator = value; } }

    public Boolean IncludeOperator { get { return this._includeOperator; } set { this._includeOperator = value; } }


    public override string ToString()
    {
        String param = GetValueAsString();
        if (param != null && this.IncludeOperator)
            return this.Operator + " " + param;
        else if (param != null && !this.IncludeOperator)
            return param.Trim();
        else
            return null;
    }

    protected abstract String GetValueAsString();
}

我想创建从接口和抽象类派生的类型化过滤器。每个过滤器都知道如何将特定类型转换为字符串以包含在查询中,但每个过滤器都需要遵守 IFilter 接口,它可以通过继承 Filter 基类来做到这一点。

public class IntFilter: Filter<Int64>
{
    protected override string GetValueAsString()
    {
        // Convert the integer to a string
        return this.Value.Value.ToString();
    }
}

public class BooleanFilter : Filter<Boolean>
{
    protected override string GetValueAsString()
    {
        // convert the Boolean to a BIT value 1=True / 0=False
        return (this.Value.HasValue && this.Value.Value) ? "1" : "0";
    }
}

public class DateTimeFilter : Filter<DateTime>
{
    protected override string GetValueAsString()
    {
        // Convert the DateTime to a dateTime string in the following format - 2/27/2009 12:12:22 PM
        return (this.Value.HasValue) ? this.Value.Value.ToString("G") : null;
    }
}

这就是它变得棘手的地方......我需要为字符串类型创建一个过滤器,但使用相同的接口和抽象类。

public class StringFilter : Filter<String>
{
    protected override string GetValueAsString()
    {
        // Convert the integer to a string
        return this.Value.Value.ToString();
    }
}

我需要能够将这些过滤器中的任何一个传递到以下方法中......

ExecuteQuery( IFilter filter );

您可以看到将泛型类型用于引用类型和值类型时存在问题。有谁知道我如何为所有类型的过滤器类使用相同的接口? 这可能吗?

【问题讨论】:

  • _value 的类型真的需要为 Nullable 吗?
  • 过滤器必须始终返回一个通常初始化为 NULL 的值。这可能意味着过滤器的 ToString 方法可能会返回一个字符串,例如 ...“= null”。由于调用方法可能一次处理这些列表,我不希望调用者负责确定值的状态然后做出反应。然而,老实说,我陷入了继承和 Nullable 类型的问题,我没有考虑改变我的逻辑的那部分。我会看看那个。谢谢!
  • 你能添加你想要的 ToString() 的不同输出吗?这可能有助于我了解您的目标是什么。

标签: c# generics


【解决方案1】:

您可以将 Nullable 从定义中提取出来,然后将它们传递给实现。这是一个例子:

public interface IFilter<T>
{
    T Value { get; set; }
    String Operator { get; set; }
    Boolean IncludeOperator { get; set; }
}

public abstract class Filter<T> : IFilter<T>
{
    T _value;
    String _operator = "=";
    Boolean _includeOperator = false;

    public T Value { get { return this._value; } set { this._value = value; } }

    public String Operator { get { return this._operator; } set { this._operator = value; } }

    public Boolean IncludeOperator { get { return this._includeOperator; } set { this._includeOperator = value; } }


    public override string ToString()
    {
        String param = GetValueAsString();
        if (param != null && this.IncludeOperator)
            return this.Operator + " " + param;
        else if (param != null && !this.IncludeOperator)
            return param.Trim();
        else
            return null;
    }

    protected abstract String GetValueAsString();
}

public class IntFilter : Filter<Nullable<Int64>>
{
    protected override string GetValueAsString()
    {
        // Convert the integer to a string
        return this.Value.HasValue ? this.Value.ToString() : "0";
    }
}

public class BooleanFilter : Filter<Nullable<Boolean>>
{
    protected override string GetValueAsString()
    {
        // convert the Boolean to a BIT value 1=True / 0=False
        return (this.Value.HasValue && this.Value.Value) ? "1" : "0";
    }
}

public class DateTimeFilter : Filter<Nullable<DateTime>>
{
    protected override string GetValueAsString()
    {
        // Convert the DateTime to a dateTime string in the following format - 2/27/2009 12:12:22 PM
        return (this.Value.HasValue) ? this.Value.Value.ToString("G") : null;
    }
}

public class StringFilter : Filter<String>
{
    protected override string GetValueAsString()
    {
        return string.IsNullOrWhiteSpace(Value) ? "" : Value;
    }
}

【讨论】:

  • 这个解决方案出现的问题是,当我在 GetValueAsString() 方法中评估“this.Value”(_value 字段的属性)时,我需要使用“this.Value.HasValue”来确定该值是否已设置,如果它不是 Nullable 值,则该值将不可用。从抽象类中删除可空值后,我尝试使用可空值覆盖派生类中的字段和属性定义,但出现错误。(类型必须为“长”以匹配被覆盖的成员“过滤器.Value”)。是否有其他方法可以确定是否未设置值类型?
  • 因为 GetValueAsString 是抽象的并且在子进程中实现,所以在编译时你就会知道真正的类型是什么,因此这个实现在我的测试中有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
相关资源
最近更新 更多