2014-03-05 63 views
2

我已經閱讀了幾個類似於我的問題的問題,但我對這些概念的理解缺乏一般答案不足以回答我的具體問題的機會, :在c中使用反射設置複雜屬性值

我有個域對象我從分貝呼叫實例:

public class dbRecord { 
    public decimal RecordCode {get;set;} 
    public string FirstName {get; set;} 
    ... 40 more fields .... 
} 

我有另一個存儲過程調用拉動列元數據(未示出),我需要與第一對象合併並創建:

public class ViewRecord { 
    public MetadataRecord<decimal> RecordCode {get;set;} 
    public MetadataRecord<string> FirstName {get; set;} 
    ... 40 more fields .... 
} 

的MetadataRecord對象是這樣的:

public class MetadataRecord<T>{ 
    public T ColumnValue {get;set;} 
    public bool IsFrozen {get;set;} 
    public string ValidatorFieldName {get;set;} 
} 

我可以通過手動映射這樣創建ViewRecord對象:

var newFile = new ViewRecord(); 
newFile.RecordCode.ColumnValue = dbRecord.RecordCode; 
... 40 more times ... 

但我想我可以使用反射來打造了這一點:

var startFile = ...dbRecord from db result... 
var newFile = new ViewRecord(); 
foreach (var startProp in startFile.GetType().GetProperties()) { 
    foreach (var newProp in newFile.GetType().GetProperties()) { 
     if (startProp.Name == newProp.Name) { 
       PropertyInfo valProp = typeof(MetadataRecord<>).GetProperty("ColumnValue"); 
        var data = startProp.GetValue(startFile, null); 
        valProp.SetValue(valProp, data, null); 
     } 
    } 
} 

這樣一直工作到我嘗試設置值的位置,並且我得到以下例外:

無法在ContainsGenericParameters爲true的類型或方法上執行後期操作。

任何人都可以幫助我找出一個不同的/更好的方式來使這項工作?整個問題是我們需要在運行時添加到數據庫記錄的字段級元數據,這導致了我的這個兔子洞!

任何幫助,將不勝感激。

UPDATE 好吧,我現在看到的,newPropType已被實例化並分配:

var instanceType = Activator.CreateInstance(newPropType); 
... 
valProp.SetValue(instanceType, data); 
newProp.SetValue(newFile, instanceType); 

謝謝您的回答,安德魯!

道具也給[email protected]給我提示Activator.CreateInstance。

回答

-1

您需要完全指定元數據屬性的通用類型。

PropertyInfo valProp = typeof(MetadataRecord<>).MakeGenericType(startProp.PropertyType).GetProperty("ColumnValue"); 

,或者其可讀性:

Type newPropType = typeof(MetadataRecord<>).MakeGenericType(startProp.PropertyType); 
PropertyInfo valProp = newPropType.GetProperty("ColumnValue"); 

而且你需要使用的元數據對象的值設置行:

var metadataObj = newProp.GetValue(newFile); 
valProp.SetValue(metadataObj, data, null);