Чтение общих значений из списка общих объектов - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь перебрать список универсальных объектов, вызывая Condition<T> для чтения универсального поля Value. Я следовал за этим вопросом, чтобы иметь возможность хранить List<Condition<T>>. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что я не могу использовать поле Value в цикле. Что мне нужно изменить, чтобы использовать поле Value?

Main

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.

Main - Test

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 голосов
/ 09 мая 2018

У вас есть синтаксические ошибки в коде, такие как отсутствие общедоступной области ваших перечислений и 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 ";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...