从通用对象列表中读取通用值

Reading Generic Value from List of Generic Objects

我正在尝试遍历通用对象列表调用 Condition<T> 以读取通用字段 Value。我遵循了 this 的问题,以便能够存储 List<Condition<T>>。我现在 运行 遇到的问题是我无法在循环中使用 Value 字段。我需要更改什么才能使用 Value 字段?

主要

string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal))
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual))

foreach (ConditionBase c in Conditions)
{
    if (c.GetType() == typeof(string))
    {
        // c.Value throws an error
        url += c.Field + " " + c.ConditionOperator + " '" + c.Value + "' and ";
    }
    else if (c.GetType() == typeof(DateTime))
    {
        // c.Value throws an error
        url += c.Field + " " + c.ConditionOperator + " " + Helpers.FormatDate(c.Value) + " and ";
    }
}

条件基础

public interface ConditionBase
{
    Field Field { get; set; }
    ConditionOperator ConditionOperator { get; set; }
}

条件

public class Condition<T> : ConditionBase
{
    private Field _Field;
    private T _Value;
    private ConditionOperator _ConditionOperator;

    public Condition(Field field, T value, ConditionOperator condition)
    {
        this._Field = field;
        this._Value = value;
        this._ConditionOperator = condition;
    }

    public Field Field
    {
        get
        {
            return this._Field;
        }
        set
        {
            if (this._Field != value)
            {
                this._Field = value;
            }
        }
    }

    public T Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            if (!EqualityComparer<T>.Default.Equals(this._Value, value))
            {
                this._Value = value;
            }
        }
    }

    public ConditionOperator ConditionOperator
    {
        get
        {
            return this._ConditionOperator;
        }
        set
        {
            if (this._ConditionOperator != value)
            {
                this._ConditionOperator = value;
            }
        }
    }
}

枚举

public enum Field{
    Field1,
    Field2
}

public enum ConditionOperator{
    Equal,
    NotEqual,
    GreaterThan,
    LessThan
}

解决方案

此解决方案基于@orhtej2 的评论和@Igor 的回答。

主要 - 测试

static void Main(string[] args)
{
    var x1 = new Condition<int>(new Field(), 123, ConditionOperator.Equal);
    var x2 = new Condition<string>(new Field(), "test", ConditionOperator.Equal);
    var x3 = new Condition<DateTime>(new Field(), new DateTime(2018,5,5), ConditionOperator.Equal);

    var qqq = new List<ConditionBase>();

    qqq.Add(x1);
    qqq.Add(x2);
    qqq.Add(x3);

    foreach (ConditionBase c in qqq)
    {
        Console.WriteLine(c.GetValue());
    }
    Console.ReadLine();
}

条件基础

public interface ConditionBase
{
    Field Field { get; set; }
    ConditionOperator ConditionOperator { get; set; }
    string GetValue();
}

条件

public class Condition<T> : ConditionBase
{
    private Field _Field;
    private T _Value;
    private ConditionOperator _ConditionOperator;

    public Condition(Field field, T value, ConditionOperator condition)
    {
        this._Field = field;
        this._Value = value;
        this._ConditionOperator = condition;
    }

    public Field Field
    {
        get
        {
            return this._Field;
        }
        set
        {
            if (this._Field != value)
            {
                this._Field = value;
            }
        }
    }

    public T Value
    {
        get
        {
            return this._Value;
        }
        set
        {
            if (!EqualityComparer<T>.Default.Equals(this._Value, value))
            {
                this._Value = value;
            }
        }
    }

    public ConditionOperator ConditionOperator
    {
        get
        {
            return this._ConditionOperator;
        }
        set
        {
            if (this._ConditionOperator != value)
            {
                this._ConditionOperator = value;
            }
        }
    }

    public string GetValue()
    {
        if (Value is string)
        {
            return "'" + Value.ToString() + "'";
        }
        else if (Value is DateTime)
        {
            return Helpers.FormatDate(Convert.ToDateTime(Value));
        }
        else
        {
            return Value.ToString();
        }            
    }
}

枚举

public enum Field{
    Field1,
    Field2
}

public enum ConditionOperator{
    Equal,
    NotEqual,
    GreaterThan,
    LessThan
}

您的代码中存在语法错误,例如您的枚举缺少 public 范围和 ConditionOperator.Equal(不是 ConditionOperator.Equals),但这里的旁白是修复方法。

  1. Conditions 应该是类型 List<ConditionBase>
  2. 在列表上使用 OfType 检索结果类型并将其转换为 Condition<string>。我认为这是你添加支票的意图 c.GetType() == typeof(string)
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));

foreach (var c in Conditions.OfType<Condition<string>>())
{
    url += c.Field + " " + c.ConditionOperator + " '" + c.Value + "' and ";
}

如果您想要一个可以在所有实例上访问的通用 属性 而无需考虑通用类型约束,那么您需要相应地扩展基本接口。

public interface ConditionBase
{
    Field Field { get; set; }
    ConditionOperator ConditionOperator { get; set; }
    object FieldValue { get; }
}

public class Condition<T> : ConditionBase
{
  /* I only included the added code in this type */
  public object FieldValue
  {
      get { return (object) this.Value; }
  }
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));

foreach (var c in Conditions)
{
    url += c.Field + " " + c.ConditionOperator + " '" + c.FieldValue + "' and ";
}

根据您问题的变化,您似乎想将您的值输出到一个字符串中。为您的类型添加一个字符串格式化程序。

/* I only included the added code in this type */
public class Condition<T> : ConditionBase
{
  private Func<T, string> _formatValue;
  public Condition(Field field, T value, ConditionOperator condition, Func<T, string> formatValue)
  {
    this._Field = field;
    this._Value = value;
    this._ConditionOperator = condition;
    this._formatValue = formatValue;
  }

  public override string ToString()
  {
      return this._formatValue(this.Value);
  }
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal, (val)=> val.ToString()));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual, (val)=> val));

foreach (var c in Conditions)
{
    url += c.Field + " " + c.ConditionOperator + " '" + c.ToString() + "' and ";
}