反射 - 使用参数

时间:2016-12-01 15:56:55

标签: c# reflection enums

我从已加载的程序集中读取类型,例如:

var someType = loadedAssemblies
            .Where(a => a != null && a.FullName.StartsWith("MY."))
            .SelectMany(a => a.GetTypes())
            .Distinct()
            .ToArray()[0];

如果counstructor有参数,我可以阅读:

ParameterInfo[] parameters = classType.GetConstructors()[0].GetParameters();

我想使用默认参数值调用构造函数,或者如果参数是枚举,则使用第一个枚举值。 如果只有一个参数并且它是枚举,则它的工作方式如下:

object curObject = Activator.CreateInstance(classType, new object[] { parameters[0].ParameterType.GetEnumValues().GetValue(0) });

如果有更多参数,我该怎么做? 我需要创建对象来读取属性:

var propertyInfo = someType.GetProperty("EntityType");
string entityType = propertyInfo.GetValue(curObject, null).ToString();

2 个答案:

答案 0 :(得分:6)

好吧,你可以创建自己的Factory和write方法,用它们的默认参数检查类型的构造函数:

public static class MyFactory
{
    public static T MyCreateInstance<T>()
        where T : class
    {
        return (T) MyCreateInstance(typeof (T));
    }

    public static object MyCreateInstance(Type type)
    {
        var ctor = type
            .GetConstructors()
            .FirstOrDefault(c => c.GetParameters().Length > 0);

        return ctor != null
            ? ctor.Invoke
                (ctor.GetParameters()
                    .Select(p =>
                        p.HasDefaultValue? p.DefaultValue :
                        p.ParameterType.IsValueType && Nullable.GetUnderlyingType(p.ParameterType) == null
                            ? Activator.CreateInstance(p.ParameterType)
                            : null
                    ).ToArray()
                )
            : Activator.CreateInstance(type);
    }
}

然后你可以使用这个方法:

var classType = loadedAssemblies
            .Where(a => a != null && a.FullName.StartsWith("MY."))
            .SelectMany(a => a.GetTypes())
            .Distinct()
            .ToArray()[0];

var curObject = MyFactory.MyCreateInstance(classType);

// This will return an array of values

object[] values = classType
                 .GetFields()
                 .Select(f => f.GetValue(curObject))
                 .ToArray();

P.S。 这是DotNet fiddle example

  

更新:

根据您使用的方案更改代码。现在我们有两种方法, 一个返回对象,另一个可以将其转换为类型T.

我还更新了DotnetFiddle,请检查一下。

答案 1 :(得分:2)

您可以创建一个帮助方法来获取类型的默认值:

private static object GetDefaultValue(Type type)
{
    if (type.IsEnum) return type.GetEnumValues().GetValue(0);
    if (type.IsValueType) return Activator.CreateInstance(type);
    return null;
}

然后,您可以获取参数的默认值:

var parameters = constructor.GetParameters()
                            .Select(p => GetDefaultValue(p.ParameterType))
                            .ToArray();

并调用ConstructorInfo来获取实例:

var obj = constructor.Invoke(parameters);

如果构造函数的参数具有默认值并且您想要使用它们,则可以执行以下操作:

var parameters = constructor
    .GetParameters()
    .Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType))
    .ToArray();