我想使用Reflection动态生成任何类,但是当该类具有与其他类一样的属性时,我遇到了问题。在上面的示例中,我重现了一部分代码,以显示同样的困难。我不能将对象转换为地址。
你能帮我吗?
public class Destinatary
{
public string DetinataryID { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Place { get; set; }
public string PostalCode { get; set; }
}
class Program
{
static void Main(string[] args)
{
Destinatary destinataryTest = new Destinatary();
Type type = typeof(Destinatary);
destinataryTest = GenerateDataSample(destinataryTest);
Console.WriteLine($"Name: {destinataryTest.Name}");
Console.WriteLine($"Place: {destinataryTest.Address.PostalCode}");
Console.WriteLine($"City: {destinataryTest.Address.City.Name}");
Console.ReadLine();
}
private static T GenerateDataSample<T>(T classToWork)
{
Type typeToWork = typeof(T);
object tipoInstance = Activator.CreateInstance(typeToWork);
foreach (var classProperty in typeToWork.GetProperties())
{
if (classProperty.PropertyType.FullName.StartsWith("System."))
{
var propertyVal = RandomString(10,false );
classProperty.SetValue(tipoInstance, propertyVal, null);
}
else
{
var instanceIntermediate = Activator.CreateInstance(classProperty.PropertyType);
instanceIntermediate = GenerateDataSample(instanceIntermediate);
classProperty.SetValue(tipoInstance, instanceIntermediate, null); //here there is a probleman (Cant convert Object to Address)
}
}
return (T)tipoInstance;
}
}
答案 0 :(得分:1)
泛型在编译时而不是在运行时解析。
在这一行
instanceIntermediate = GenerateDataSample(instanceIntermediate);
instanceIntermediate是一个Address对象,但此处的编译器仅知道它是一个对象。因此它调用了GenerateDataSample,它将在此行中构造一个对象
object tipoInstance = Activator.CreateInstance(typeToWork);
要让GenerateDataSample创建对象classToWork类型的实例,请使用
object tipoInstance = Activator.CreateInstance(classToWork.GetType());
答案 1 :(得分:1)
为什么要转换值?该对象已经是Address
类型,并且set方法声明为
public void SetValue (object obj, object value);
即,它接受类型为object
的变量。
调用GenerateDataSample<T>()
时会发生问题,因为T
是在编译时确定的,并且instanceIntermediate
的编译时类型是object
,因此GenerateDataSample
将始终尝试为属性创建类型为System.Object
的对象。不要将GenerateDataSample
设为通用。
此外,您实际上不需要传递实例,而只需将类型传递给GenerateDataSample
。
private static object GenerateDataSample(Type typeToWork)
{
object tipoInstance = Activator.CreateInstance(typeToWork);
foreach (PropertyInfo classProperty in typeToWork.GetProperties()) {
object propertyVal;
if (classProperty.PropertyType == typeof(string)) {
propertyVal = RandomString(10, false);
} else {
propertyVal = GenerateDataSample(classProperty.PropertyType);
}
classProperty.SetValue(tipoInstance, propertyVal);
}
return tipoInstance;
}
您还可以创建重载的通用版本:
private static T GenerateDataSample<T>()
{
return (T)GenerateDataSample(typeof(T));
}
然后您可以使用以下方法创建示例数据:
Destinatary destinataryTest = GenerateDataSample<Destinatary>();
答案 2 :(得分:0)
var instanceIntermediate = Activator.CreateInstance(...
-在这一行,instanceIntermediate
的编译时间类型为object
。因此,当您致电GenerateDataSample(instanceIntermediate)
时,它是在致电GenerateDataSample<object>(instanceIntermediate)
而不是您可能期望的GenerateDataSample<Address>(instanceIntermediate)
。
修复:由于GenerateDataSample
实际上并不关心输入参数,而只是键入-将其从通用方法更改为常规方法,并采用类型-object GenerateDataSample(Type typeToWork)