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

时间:2018-05-09 17:39:44

标签: c# generics generic-list

我正在尝试遍历通用对象列表,调用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&amp;的评论。 @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
}

1 个答案:

答案 0 :(得分:3)

您的代码中存在语法错误,例如您的枚举缺少公开范围和ConditionOperator.Equal(不是ConditionOperator.Equals),但是这里的答案就是修复。

  1. Conditions应为List<ConditionBase>
  2. 类型
  3. 使用列表上的OfType检索结果类型并将其转换为Condition<string>。我认为这是您添加支票c.GetType() == typeof(string)
  4. 的意图
    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 ";
    }