Nik*_*ani 8 c# reflection dynamic methodinfo parameterinfo
我需要使用C#通过反射调用类型的方法.
在运行时,我的数据将包含一个包含名称/值对的Dictionary.字典中的名称将对应于我将调用的方法上的参数名称.此外,在运行时,我将有一个任意的程序集限定类型名称和方法名称.在设计时,我不知道类型和方法,除了该方法将接受int,string,DateTime,bool,int [],string [],DateTime []或bool类型的可变数量的参数[].
我没有问题,我可以使用反射创建该类型的实例并调用该方法.当我调用时,我不得不将字典中的字符串值转换为方法所需的相应类型:
someMethodInfo.Invoke(instance, new [] { ... })
Run Code Online (Sandbox Code Playgroud)
我知道我需要通过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());
}
Run Code Online (Sandbox Code Playgroud)
它支持原始类型、可空值和原始类型数组。如果您要使用不支持 IConvertible 接口的类型 - 最好为每个单独的类型实现自定义转换器。
可以使用 Linq 以更优雅的方式编写它。
维塔利