从通用对象列表中读取通用值
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
),但这里的旁白是修复方法。
Conditions
应该是类型 List<ConditionBase>
- 在列表上使用
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 ";
}
我正在尝试遍历通用对象列表调用 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
),但这里的旁白是修复方法。
Conditions
应该是类型List<ConditionBase>
- 在列表上使用
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 ";
}