C#类中泛型类型的泛型属性设置程序



我正在尝试在ItemsRow类中通用地设置字段值(以及其他格式相似的字段值,但属性和字段不同。

我想做一些类似于我对硬编码所做的事情

public Dictionary<object, Action<T, object>> SetFieldValues = new Dictionary<object, Action<T, object>>
{
{"Description", (m,v) => m.Description = (string)v};
}

public class Mapping<T> where T:Row
{

public Dictionary<object, Action<T, object>> SetFieldValues(string[] headers)
{
Dictionary<object, Action<T, object>> myDict = new Dictionary<object, Action<T, object>>();
//  Activator 
var objectType = typeof(T); // Type.GetType(T);
var tRow = Activator.CreateInstance(objectType) as Row;
foreach (var item in headers)
{
var myfield = tRow.FindFieldByPropertyName(item);
//myDict[item] = myfield = 
//myDict[item] = (m, v) => m.FindFieldByPropertyName(item) = (Type.GetType(myfield.Type.ToString()))v;
}
// I want this to be dynamic header[i],(m,v) => m.(property to set for object) = (cast to type m.property type)v
//{"ItemName", (m,v) => m.ItemName = (string)v},
//{"Description", (m,v) => m.Description = (string)v},

return myDict;
}

//类名将不同,属性和字段将不同。。

public sealed class ItemsRow : Row
{
public String ItemName
{
get { return Fields.ItemName[this]; }
set { Fields.ItemName[this] = value; }
}
public String Description
{
get { return Fields.Description[this]; }
set { Fields.Description[this] = value; }
}

public static readonly RowFields Fields = new RowFields().Init();
public ItemsRow()
: base(Fields)
{
}
public class RowFields : RowFieldsBase
{
public StringField ItemName;
public StringField Description;
}
}

基本类

================================================

using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
namespace Serenity.Data
{
[JsonConverter(typeof(JsonRowConverter))]
public abstract partial class Row : IEntityWithJoins, 
INotifyPropertyChanged, IEditableObject
#if !COREFX
, IDataErrorInfo
#endif
{
internal RowFieldsBase fields;
internal bool[] assignedFields;
internal Hashtable dictionaryData;
internal bool ignoreConstraints;
internal object[] indexedData;
internal bool tracking;
internal bool trackWithChecks;
protected Row(RowFieldsBase fields)
{
if (fields == null)
throw new ArgumentNullException("fields");
this.fields = fields.InitInstance(this);
TrackAssignments = true;
}
public void CloneInto(Row clone, 
bool cloneHandlers)
{
clone.ignoreConstraints = ignoreConstraints;
foreach (var field in GetFields())
field.Copy(this, clone);
clone.tracking = tracking;
if (tracking)
{
if (assignedFields != null)
{
clone.assignedFields = new bool[assignedFields.Length];
Array.Copy(assignedFields, clone.assignedFields, assignedFields.Length);
}
}
else
clone.assignedFields = null;
clone.trackWithChecks = trackWithChecks;
clone.originalValues = originalValues;
if (dictionaryData != null)
clone.dictionaryData = (Hashtable)this.dictionaryData.Clone();
else
clone.dictionaryData = null;
if (indexedData != null)
{
clone.indexedData = new object[indexedData.Length];
for (var i = 0; i < indexedData.Length; i++)
clone.indexedData[i] = indexedData[i];
}
else
clone.indexedData = null;
if (previousValues != null)
clone.previousValues = previousValues.CloneRow();
else
clone.previousValues = null;
if (cloneHandlers)
{
clone.postHandler = this.postHandler;
clone.propertyChanged = this.propertyChanged;
if (this.validationErrors != null)
clone.validationErrors = new Dictionary<string, string>(this.validationErrors);
else
clone.validationErrors = null;
}
}
public Row CloneRow()
{
var clone = CreateNew();
CloneInto(clone, true);
return clone;
}
public virtual Row CreateNew()
{
if (fields.rowFactory == null)
throw new NotImplementedException();
return fields.rowFactory();
}
internal void FieldAssignedValue(Field field)
{
if (assignedFields == null)
assignedFields = new bool[fields.Count];
assignedFields[field.index] = true;
if (validationErrors != null)
RemoveValidationError(field.PropertyName ?? field.Name);
if (propertyChanged != null)
{
if (field.IndexCompare(previousValues, this) != 0)
{
RaisePropertyChanged(field);
field.Copy(this, previousValues);
}
}
}
public Field FindField(string fieldName)
{
return fields.FindField(fieldName);
}
public Field FindFieldByPropertyName(string propertyName)
{
return fields.FindFieldByPropertyName(propertyName);
}
public RowFieldsBase GetFields()
{
return fields;
}
public int FieldCount
{
get { return fields.Count; }
}
public bool IsAnyFieldAssigned
{
get
{
return tracking && assignedFields != null;
}
}
public bool IgnoreConstraints
{
get { return ignoreConstraints; }
set { ignoreConstraints = value; }
}
public string Table
{
get { return fields.TableName; }
}
public bool TrackAssignments
{
get
{ 
return tracking;
}
set 
{
if (tracking != value)
{
if (value)
{
if (propertyChanged != null)
previousValues = this.CloneRow();
tracking = value;
}
else
{
tracking = false;
trackWithChecks = false;
assignedFields = null;
}
}
}
}
public bool TrackWithChecks
{
get 
{
return tracking && trackWithChecks;
}
set
{
if (value != TrackWithChecks)
{
if (value && !tracking)
TrackAssignments = true;
trackWithChecks = value;
}
}
}
private Field FindFieldEnsure(string fieldName)
{
var field = FindField(fieldName);
if (ReferenceEquals(null, field))
throw new ArgumentOutOfRangeException("fieldName", String.Format(
"{0} has no field with name '{1}'.", this.GetType().Name, fieldName));
return field;
}
public object this[string fieldName]
{
get 
{
var field = FindFieldByPropertyName(fieldName) ??
FindField(fieldName);
if (ReferenceEquals(null, field))
{
if (dictionaryData != null)
return dictionaryData[fieldName];
return null;
}
return field.AsObject(this); 
}
set
{
(FindFieldByPropertyName(fieldName) ?? 
FindFieldEnsure(fieldName)).AsObject(this, value);
}
}
public void SetDictionaryData(object key, object value)
{
if (value == null)
{
if (dictionaryData == null)
return;
dictionaryData[key] = null;
}
else
{
if (dictionaryData == null)
dictionaryData = new Hashtable();
dictionaryData[key] = value;
}
}
public object GetDictionaryData(object key)
{
if (dictionaryData != null)
return dictionaryData[key];
return null;
}

internal void SetIndexedData(int index, object value)
{
if (value == null)
{
if (indexedData == null)
return;
indexedData[index] = null;
}
else
{
if (indexedData == null)
indexedData = new object[this.FieldCount];
indexedData[index] = value;
}
}
internal object GetIndexedData(int index)
{
if (indexedData != null)
return indexedData[index];
return null;
}
public bool IsAssigned(Field field)
{
if (assignedFields == null)
return false;
return assignedFields[field.index];
}
public void ClearAssignment(Field field)
{
if (assignedFields == null)
return;
assignedFields[field.index] = false;
for (var i = 0; i < assignedFields.Length; i++)
if (assignedFields[i])
return;
assignedFields = null;
}
public bool IsAnyFieldChanged
{
get
{
if (originalValues == null)
return false;
for (var i = 0; i < fields.Count; i++)
if (fields[i].IndexCompare(originalValues, this) != 0)
return true;
return false;
}
}
IDictionary<string, Join> IHaveJoins.Joins
{
get { return fields.Joins; }
}
}
}

很抱歉我昨天没能回复你,但承诺就是承诺:(。在写这段代码的时候,我开始怀疑你的头实际上是什么样子的。您将如何确定哪个属性属于哪个标头?除非你对我在你的代码中可能缺少的东西有某种认可。

但总体思路是:

当然,这是基于这样一个前提,即标头是键值对,其中键是要使用的属性的标识符。

static void Main(string[] args)
{
var values = new Dictionary<string, string>()
{
["Title"] = "Test",
["Amount"] = "5",
["Description"] = "Some description"
};
var target = new TestClass();
var setters = GetPropertySetters(target);
foreach(KeyValuePair<string, string> value in values)
{
if (setters.ContainsKey(value.Key))
setters[value.Key].Invoke(value.Value);
}
Console.WriteLine(JsonConvert.SerializeObject(target));
Console.ReadLine();
}
public static Dictionary<string, Action<string>> GetPropertySetters<T>(T source)
{
var result = new Dictionary<string, Action<string>>(StringComparer.OrdinalIgnoreCase);
foreach (PropertyInfo pi in typeof(T).GetProperties())
result.Add(pi.Name, (string value) => { pi.SetValue(source, Convert.ChangeType(value, pi.PropertyType)); });
return result;
}
public class TestClass
{
public string Title { get; set; }
public int Amount { get; set; }
public string Description { get; set; }
}

最新更新