当属性值为null时,InvokeMember“Method not found”异常

时间:2013-12-03 19:04:01

标签: c# .net reflection

我有这个课程:

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...

}

1 个答案:

答案 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地图有关。