Reflection - Call constructor with parameters

后端 未结 2 1765
没有蜡笔的小新
没有蜡笔的小新 2021-01-04 19:13

I read type from loaded assemblies for example:

var someType = loadedAssemblies
            .Where(a => a != null && a.FullName.StartsWith(\"MY.\"         


        
相关标签:
2条回答
  • 2021-01-04 19:30

    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);
        }
    }
    

    And then you can use this method:

    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. Here is a DotNet fiddle example.

    Update:

    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.

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

    0 讨论(0)
  • 2021-01-04 19:45

    You can make a helper method to get default value of a type:

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

    Then, you can get default values of the parameters:

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

    And invoke the ConstructorInfo to get the instance:

    var obj = constructor.Invoke(parameters);
    

    If the constructor's parameters have default values and you want to use them, you can do something like this:

    var parameters = constructor
        .GetParameters()
        .Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType))
        .ToArray();
    
    0 讨论(0)
提交回复
热议问题