如何在c#中使用反射调用方法时对参数进行自动类型转换



我需要使用c#通过反射调用类型上的方法。

在运行时,我的数据将由包含名称/值对的Dictionary组成。Dictionary中的名称将对应于我将调用的方法的参数名称。此外,在运行时,我将有一个任意的程序集限定类型名和一个方法名。在设计时,我将不知道类型和方法,除了该方法将接受int, string, DateTime, bool, int[], string[], DateTime[]或bool[]类型的可变数量的参数。

我可以使用反射创建该类型的实例并调用该方法。当我调用

时,我必须将字典中的字符串值转换为方法所需的适当类型,这时我陷入了困境:
someMethodInfo.Invoke(instance, new [] { ... })

我知道我可能需要通过MethodInfo.GetParameters()枚举,并为每个参数执行类型转换。我想弄清楚的是如何做到这一点,理想情况下,如何有效地做到这一点。

到目前为止,我的研究涉及到挖掘MVC源代码,因为它在将表单值传递给ActionMethod时做了类似的事情。我发现ActionMethodDispatcher,但它使用LINQ表达式,我不熟悉。

我也看了类似的问题在SO,但没有找到任何回答我的问题。

下面是一些可用于参数转换的代码:

public object ConvertSingleItem(string value, Type newType)
{
    if (typeof(IConvertible).IsAssignableFrom(newType))
    {
        return Convert.ChangeType(value, newType);
    }
    else
    {
        // TODO: Add custom conversion for non IConvertible types
        var converter = CustomConvertersFactory.GetConverter(newType);
        return converter.Convert(value);
    }
}
public object ConvertStringToNewNonNullableType(string value, Type newType)
{
    // Do conversion form string to array - not sure how array will be stored in string
    if (newType.IsArray)
    {
        // For comma separated list
        Type singleItemType = newType.GetElementType();
        var elements = new ArrayList();
        foreach (var element in value.Split(','))
        {
            var convertedSingleItem = ConvertSingleItem(element, singleItemType);
            elements.Add(convertedSingleItem);
        }
        return elements.ToArray(singleItemType);
    }
    return ConvertSingleItem(value, newType);
}
public object ConvertStringToNewType(string value, Type newType)
{
    // If it's not a nullable type, just pass through the parameters to Convert.ChangeType
    if (newType.IsGenericType && newType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    {
        if (value == null)
        {
            return null;
        }
        return ConvertStringToNewNonNullableType(value, new NullableConverter(newType).UnderlyingType);
    }
    return ConvertStringToNewNonNullableType(value, newType);
}
public object CallMethod(object instance, MethodInfo methodInfo, Dictionary<string, string> parameters)
{
    var methodParameters = methodInfo.GetParameters();
    var parametersForInvocation = new List<object>();
    foreach (var methodParameter in methodParameters)
    {
        string value;
        if (parameters.TryGetValue(methodParameter.Name, out value))
        {
            var convertedValue = ConvertStringToNewType(value, methodParameter.ParameterType);
            parametersForInvocation.Add(convertedValue);
        }
        else
        {
            // Get default value of the appropriate type or throw an exception
            var defaultValue = Activator.CreateInstance(methodParameter.ParameterType);
            parametersForInvocation.Add(defaultValue);
        }
    }
    return methodInfo.Invoke(instance, parametersForInvocation.ToArray());
}

它支持基本类型、空值和基本类型的数组。当你要使用不支持IConvertible接口的类型时,最好为每个单独的类型实现自定义转换器。

可以用更优雅的方式用Linq来写。

维塔利

要转换的值应该是一个对象,否则在标准类型之外的转换将不起作用。您可以轻松地在类型之间进行转换,如下所示:

object value = false; // false
Type chType = typeof(String); // System.String
object newValue = Convert.ChangeType(value, chType); // "false"

就这么简单。如果你想要一个方法:

public object ConvertType(object value, Type conversionType)
{
    //Check if type is Nullable
    if (conversionType.IsGenericType &&
        conversionType.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        //If the type is Nullable and the value is null
        //Just return null
        if (value == null)
        {
            return null;
        }
        //Type is Nullable and we have a value, override conversion type to underlying
        //type for the Nullable to avoid exception in Convert.ChangeType
        var nullableConverter = new NullableConverter(conversionType);
        conversionType = nullableConverter.UnderlyingType;
    }
    return Convert.ChangeType(value, conversionType);
}

也许管理"转换器"的一个好方法是维护Dictionary<Type, IMyTypeConverter> -其中IMyTypeConverterobject Convert(string value)

相关内容

  • 没有找到相关文章

最新更新