我有这个课程:
public abstract ClassBase {
public virtual String PropertyA { get; set; }
}
和
public class Class : ClassBase{
public virtual String PropertyB { get; set; }
}
当我尝试使用这段代码设置PropertyA
的值时:
instanceOfClass.GetType().InvokeMember(
"PropertyA",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty ,
Type.DefaultBinder,
instanceOfClass,
new object[]{ "Hello world" }
);
我在instanceOfClass.PropertyA == null
时收到错误“找不到方法”。
instanceOfClass.PropertyA!=null
时,它可以正常工作。
我做错了什么?
已编辑:添加完整功能作为示例。它是DataGridView
控件上的CRUD逻辑:
public class DataGridViewCrud<T,TRepository,THandler> : UserControl
where T : class, new()
where TRepository: RepositoryBase<T,THandler>
where THandler : NhHandlerBase
{
private readonly TRepository _repository;
private List<DataGridViewField> HiddenFields { get; set; }
private List<DataGridViewField> FieldsId { get; set; }
private DataGridView _dataGridView;
private List<T> _contents;
(...) // Other methods, functions...
private void OnCellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
var isNew = e.RowIndex + 1 > _contents.Count;
var theRow = _dataGridView.Rows[e.RowIndex];
ValidateConfig();
using (var transaction = _repository.BeginTransaction())
{
T instance = null;
if (isNew)
{
instance = new T();
} else {
// Get the ID fields name defined
foreach (var fieldId in FieldsId)
{
// Get the current value for the current row
for (var i = 0; i < _dataGridView.Columns.Count; i++)
{
var columnName = _dataGridView.Columns[i].Name;
if (columnName != fieldId.FieldName) continue;
// Get instance from DB
var idValue = theRow.Cells[columnName].Value;
var criteria = _repository.GetSession().CreateCriteria<T>().Add(Restrictions.Eq(fieldId.FieldName, idValue));
instance = criteria.List<T>().SingleOrDefault();
i = _dataGridView.Columns.Count;
}
}
}
if(instance==null) throw new Exception("Imposible to get instance from DB. Check the configuration of ID fields.");
var properties = instance.GetType().GetProperties();
foreach (var property in properties)
{
for (int i = 0; i < _dataGridView.Columns.Count; i++)
{
var columnName = _dataGridView.Columns[i].Name;
var isColumnId = FieldsId.Any(f => f.FieldName == columnName);
// If is not the column (check by name), continue
if (columnName != property.Name) continue;
// Check if is Field ID and is autogenerated
DataGridViewField fieldId = null;
if(isColumnId)
{
fieldId = FieldsId.First(fi => fi.FieldName == columnName);
if (fieldId.IsAutoGenerated) continue;
}
var cellValue = fieldId!= null ? fieldId.DefaultValue : theRow.Cells[columnName].Value;
var value = new object[1];
value[0] = cellValue;
instance.GetType().InvokeMember(
property.Name,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty ,
Type.DefaultBinder,
instance,
value
);
}
}
if(isNew) {
_repository.Save(instance);
} else {
_repository.Update(instance);
}
transaction.Commit();
}
ChangeStatus(Res.RecordSuccessfullyUpdated, false);
}
catch (Exception exception)
{
ChangeStatus(exception.Message, true);
}
}
(...) // Other methods, functions...
}
答案 0 :(得分:0)
确实,value==DBNull
所以,要解决,请更换:
var cellValue = fieldId!= null ? fieldId.DefaultValue : theRow.Cells[columnName].Value;
var value = new object[1];
value[0] = cellValue;
instance.GetType().InvokeMember(
property.Name,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty ,
Type.DefaultBinder,
instance,
value
);
用这个:
var rowValue = theRow.Cells[columnName].Value ;
rowValue = rowValue is DBNull ? null : rowValue;
var cellValue = defaultValue ?? rowValue;
var value = new object[1];
value[0] = cellValue;
instance.GetType().InvokeMember(
property.Name,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty ,
Type.DefaultBinder,
instance,
value
);
现在正在努力。我怀疑这个问题与NHibernate地图有关。