2014-03-05 61 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);