Linq Expression用可选的args创建Type实例?

时间:2013-11-26 20:09:24

标签: c# linq reflection linq-expressions

使用Linq表达式创建实例时,以下代码可以正常创建具有0参数的类型实例。

var newExpression = Expression.New(type);

但是,如果类型具有可选参数,即每个arg都是可选的,因此该类型基本上与new()兼容,那么上面的代码将失败。

所以我想我必须为每个可选的arg传递表达式。 那么我如何得到与每个参数相关的默认值?

如何从每个arg的ParameterInfo中获取默认值?

2 个答案:

答案 0 :(得分:3)

您可以使用DefaultValue属性:

ParameterInfo parameter = //
if(parameter.HasDefaultValue)
{
    object defaultValue = parameter.DefaultValue;
}

您可以使用Expression.Constant创建表达式:

public class SomeClass
{
    public SomeClass(int i = 3, string str = "Default")
    {
    }
}

ConstructorInfo ci = typeof(SomeClass).GetConstructor(new[] { typeof(int), typeof(string) });
var paramExprs = ci.GetParameters().Select(p => Expression.Constant(p.DefaultValue)).ToArray();
var newExpr = Expression.New(ci, paramExprs);

答案 1 :(得分:2)

因此,如果你知道给定的构造函数具有所有默认值,那么你可以使用反射来使它们足够简单。

public static Expression Construct(ConstructorInfo constructor)
{
    return Expression.New(constructor,
        constructor.GetParameters()
        .Select(param => Expression.Constant(param.DefaultValue)));
}

这仍然会让您遇到查找具有所有默认值的构造函数的问题。

您可以利用以下模式查找所有可能的有效构造函数,但您仍需要选择其中一个:

typeof(Foo).GetConstructors()
    .Where(constructor => constructor.GetParameters()
        .All(param => param.HasDefaultValue));

(请注意,这也将匹配无参数构造函数。)