繁体   English   中英

使用反射调用方法

[英]Use reflection to invoke method

在使用Azure ServiceFabric时,我们使用StateManager.GetStateAsync方法来获取值,该方法可用于在类之类的对象类型中获取值。

我正在尝试下面的代码

var typeObj = Activator.CreateInstance(type);
var method = typeof(IActorStateManager).GetMethod(nameof(IActorStateManager.GetStateAsync));
            var generic = method.MakeGenericMethod(type);
            dynamic task = generic.Invoke(typeObj, new[] { stateName })
            object result = await task;

通过这种方法,我得到了例外。

Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146232829
    HelpLink: null
    InnerException: null
    Message: "Object does not match target type."
    Source: "mscorlib"
    StackTrace: "at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
                at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)  
                at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)   
                at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)"
    TargetSite: {Void CheckConsistency(System.Object)}

最有可能的是,这里有些事情被弄糊涂了。 如果您的代码就是您实际执行的代码,则说明您过度/滥用了type变量。

让我们确定该type为具体的ActorStateManager 然后

var typeObj = Activator.CreateInstance(type); // typeobj is now ActorStateManager

错误可能在这里:

var generic = method.MakeGenericMethod(type); 
// generic is now StateManager.GetStateAsync<ActorStateManager>

您的意图不是创建StateManager.GetStateAsync<ActorStateManager> ,而是创建StateManager.GetStateAsync<ActorStateManager> StateManager.GetStateAsync<bool>StateManager.GetStateAsync<DateTime>

另外,我的GetStateAsync 将(可选)cancellationToken作为第二个参数,最好在进行反射时明确显示。

所以我想这就是您想要做的:

    public async Task<object> TryLotsOfTypesAndIgnoreErrors(string stateName)
    {
        var typeObj = Activator.CreateInstance(typeof(ActorStateManager));
        foreach (var typeParam in new[] {typeof(bool), typeof(string)})
        {
            try
            {
                var method = typeof(IActorStateManager).GetMethod(nameof(IActorStateManager.GetStateAsync));
                var generic = method.MakeGenericMethod(typeParam);
                var task = (Task) generic.Invoke(typeObj, new object[] { stateName, CancellationToken.None });
                await task;
                return task.GetType().GetProperty(nameof(Task<object>.Result))?.GetValue(task);
            }
            catch
            {
                // TODO: Catch only exception specific to type mismatch
            }
        }
        return null;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM