反射-使用参数调用构造函数 [英] Reflection - Call constructor with parameters

查看:70
本文介绍了反射-使用参数调用构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I read type from loaded assemblies for example:

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

如果同构有参数,我可以读取它们:

If counstructor has parameters, i can read them:

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

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

I would like to call constructor with default parameter values or if parameter is enum, with first enum value. If there is only one parameter and it is enum, it works like this:

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

当有更多参数时,该怎么办?我需要创建对象来读取属性:

How can I do this when there are more parameters? I need to create object to read the property:

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

推荐答案

好,您可以创建自己的Factory,并编写一个方法,该方法检查构造函数的类型并使用其默认值运行第一个参数化的ctor:

Well, you can create your own Factory, and write a method, that checks constructors for the type and runs first parameterized ctor with its default values:

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

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

        return parametrizedCtor != null
            ? parametrizedCtor.Invoke
                (parametrizedCtor.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小提琴示例.

更新:

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

The code is changed according to scenario you work with. Now we have two methods, one returns object, and another one that can convert it to type T.

我还更新了DotnetFiddle,请检查它.

I've also updated the DotnetFiddle, please check it.

这篇关于反射-使用参数调用构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆