2013-12-03 60 views
0

我有這個類:InvokeMember「未找到方法」異常,當屬性值爲null

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

}

+5

你能舉一個簡短但完整的例子來證明這個問題嗎? –

+2

你的代碼工作得很好。正如Jon Skeet指出的那樣 - 給出顯示問題的示例。請檢查出好樣品的指導 - http://www.sscce.org –

+0

好的,你的時間thx。我編輯的帖子是一個更具體的。 –

回答

0

事實上,在發生錯誤時value==DBNull

所以,解決,更換:

與此:

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地圖有關。