我的结果(xml格式,<Prop0>
,<Prop1>
,...)来自我保存到数据库表中的API。我有一个Props到我的表列的映射。我想动态创建一个对象,其中属性名称来自映射,而值来自API结果。
我可以使用映射字典和API结果直接将值保存在数据库中,但所有插入函数(远程到我的应用程序)都设计为使用对象列表。
我已经探索过System.Dynamic.ExpandoObject,但是无法动态添加属性(例如,字典)。目前,我正在使用以下通用但强类型的解决方案,其中所有属性都需要存在于类中。
internal T FetchPopulatedObject<T>(Dictionary<string, string> apiToTableMapping, Dictionary<string, string> apiResultsKeyVal, T objectToPopulate) where T : new()
{
if (objectToPopulate == null)
objectToPopulate = new T();
PropertyInfo currProp;
Type currActualType;
string valToSet = string.Empty;
int valToSetNumeric = 0;
object finalValToSet = new object();
foreach (KeyValuePair<string, string> currMap in apiToTableMapping)
{
valToSet = string.Empty;
currProp = (typeof(T).GetProperty(currMap.Value));
if (currProp == null)
{
log.Info("Could not find property for table column " + currMap.Value + ". Moving on.");
continue;
}
bool valResult = apiResultsKeyVal.TryGetValue(currMap.Key, out valToSet);
if (!valResult)
{
log.Info("Could not find value in API Results for property: " + currMap.Key + ".");
continue;
}
currActualType = Nullable.GetUnderlyingType(currProp.PropertyType) ?? currProp.PropertyType;
if (string.IsNullOrEmpty(valToSet))
{
log.Info("Property " + currProp.Name + " is of " + currProp.PropertyType.Name + " type but API attribute " +
currMap.Key + " returned an incompatible or empty value " + valToSet + ". Skipping this field.");
continue;
}
else
{
finalValToSet = Int32.TryParse(valToSet, out valToSetNumeric) ? Convert.ChangeType(valToSetNumeric, currActualType) : Convert.ChangeType(valToSet, currActualType);
}
currProp.SetValue(objectToPopulate, finalValToSet, null);
}
return objectToPopulate;
}
但是,这是不可行的,因为API结果会不断变化并添加新属性。
有人可以建议如何在不必拥有T类中的所有属性的情况下完成相同的工作吗?
答案 0 :(得分:1)
除了Emit之外,我只能想到一个动态编译类型,例如:
static Type GetMeAType( string myTypeName, string myStringPropertyName ) {
string codeToCompile = "using System; public class " + myTypeName + " {public string " +
myStringPropertyName + " { get; set; } }";
string[] references = { "System.dll", "System.Core.dll" };
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.GenerateInMemory = true;
compilerParams.TreatWarningsAsErrors = false;
compilerParams.GenerateExecutable = false;
compilerParams.CompilerOptions = "/optimize";
compilerParams.ReferencedAssemblies.AddRange( references );
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults compile = provider.CompileAssemblyFromSource( compilerParams, codeToCompile );
Module dynamicModule = compile.CompiledAssembly.GetModules()[ 0 ];
var type = dynamicModule.GetType( myTypeName );
return type;
}
答案 1 :(得分:0)
在C#中动态创建类型的唯一方法是使用T
命名空间。在这种情况下,您不能使用泛型,因为即使未指定类型list = [1,2,3,4,5]
a = list
print(a)
,它仍然意味着类型安全,这需要在编译期间创建类型。