我得到的代码有效(简化):
Assembly lib = Assembly.LoadFile("C:\\mydll.dll");
var libType = lib.GetTypes();
Type mvType = libType[0];
PropertyInfo WidthProperty = mvType.GetProperty("Width");
但是,我想使用像
这样的代码访问默认值var WidthPropertyValue = WidthProperty.GetValue(???, null);
问题是我们无法使用Activator.CreateInstance实例化对象,因为构造函数需要加载整个庞大的项目才能工作......无论如何,这不是解决该问题的重点。 问题是,是否可以使用此策略访问默认方式? 有可能用另一种方式吗? 完全不可能?
答案 0 :(得分:3)
您需要通过“默认值”澄清您的意思...它是属性类型的默认值吗?在这种情况下,对于引用类型它是null,对于值类型,它是使用默认构造函数创建的实例:
static object GetDefaultValue(PropertyInfo prop)
{
if (prop.PropertyType.IsValueType)
return Activator.CreateInstance(prop.PropertyType);
return null;
}
如果您的意思是“使用DefaultValueAttribute
声明的值”,则可以像这样检索它:
static object GetDefaultValue(PropertyInfo prop)
{
var attributes = prop.GetCustomAttributes(typeof(DefaultValueAttribute), true);
if (attributes.Length > 0)
{
var defaultAttr = (DefaultValueAttribute)attributes[0];
return defaultAttr.Value;
}
// Attribute not found, fall back to default value for the type
if (prop.PropertyType.IsValueType)
return Activator.CreateInstance(prop.PropertyType);
return null;
}
如果你想在构造函数中分配给属性的值,那么在没有创建类的实例的情况下就无法获得它(好吧,你可以反编译代码,但这并不容易......)
答案 1 :(得分:1)
如果可以访问汇编代码,我建议使用Attribute
定义默认值。
否则我认为不可能。属性默认值不是程序集元数据的一部分(默认值概念本身不存在,这就是DefaultValueAttribute
存在的原因)所以我不确定你是否可以解决创建对象实例的问题。它可以是任何东西:支持字段的默认值,构造函数中设置的某些值,它可以基于某些环境条件等。
更新:我看到一些答案/评论指向创建属性类型的默认类型。属性默认值是特定于实现的,而不是特定于类型。在许多情况下,它们可能会重合但不一定如此。
答案 2 :(得分:1)
如果在构造函数中设置了值,并且实际上无法调用构造函数,则提取值并不容易。这是因为该值实际上嵌入在构造函数的代码中。
如果你真的很勇敢并且手上有很多时间,你可以尝试使用像Cecil这样的工具直接检查IL。如果属性是简单类型(int,double,string等),那么您可以执行以下操作:
如果通过构造函数中的字段设置:
确定属性的字段名称。您可以根据编码约定来猜测名称(不是很漂亮,但可能会根据工具的意图完成工作),或者您可以进一步检查属性getter以查看它使用的字段。如果属性不仅仅返回值,那么即使这样也可能很棘手。
检查构造函数代码并查找对该字段的引用。如果构造函数调用其他设置默认值的方法,这可能会很复杂。
找到感兴趣的字段的Stfld后,请在其上方查看常量值(Ldc_I4,Ldc_R4,Ldc_R8或Ldstr。)
如果通过构造函数中的属性设置:
确定属性设置器并在代码中查找对setter的调用。
与现场案例一样,请在调用前立即检查以查看加载的常量值。
如果你真的想尝试这个,我建议先创建各种类型的构造函数并检查ildasm中的代码,以了解代码在编译时的外观。在一般情况下,自动确定默认值将非常困难,但对于“常见”案例而言可以实现,这可能足以满足您的目的。