【问题标题】:Interface from string to use as generic type从字符串接口用作泛型类型
【发布时间】:2016-11-01 17:57:52
【问题描述】:

我在 Azure 中使用 Service Fabric 并为这样的参与者设置代理:

var proxy = ActorProxy.Create<T>(actorId);

必须将 T 指定为我正在调用的参与者的接口。

假设我将接口的名称作为字符串:

var interfaceName = "IUserActor";

有没有办法通过这个字符串名称来实例化一个泛型类型?如果有,如何通过字符串名称调用给定接口中指定的方法?

所有参与者接口都继承自作为 Service Fabric 一部分的 IActor。

现在我知道不建议这样做,重点是能够从测试和管理目的访问给定参与者的参与者状态。在这种情况下,速度无关紧要,因此任何反射方法都可以。

所以,一个基本的用法示例,不使用动态接口名称:

public async Task<string> AdminGetState(ActorId actorId, string interfaceName){
   var proxy = ActorProxy.Create<IUserActor>(actorId);
   var state = await proxy.AdminGetStateJson();
   return JsonConvert.SerializeObject(state);
}

【问题讨论】:

    标签: c# generics reflection interface azure-service-fabric


    【解决方案1】:

    它既不美观也不高效,但您可以使用反射来做到这一点...

    public async Task<string> AdminGetState(ActorId actorId, string interfaceName){
    
       //Find the type information for "interfaceName".  (Assuming it's in the executing assembly)
       var interfaceType = Assembly.GetExecutingAssembly().GetType(interfaceName);
    
       //Use reflection to get the Create<> method, and generify it with this type
       var createMethod = typeof(ActorProxy).GetMethod(nameof(ActorProxy.Create)).MakeGenericMethod(interfaceType);
    
       //Invoke the dynamically reflected method, passing null as the first argument because it's static
       object proxy = createMethod.Invoke(null,new object[] { actorId });
    
       //As per your comments, find the "AdminGetStateJson" method here.  You're REALLY trusting that it exists at this point.
       var adminGetStateMethod = interfaceType.GetMethod("AdminGetStateJson");
    
       Task<string> stateTask = (Task<string>)adminGetStateMethod.Invoke(proxy, null);
    
       var state = await stateTask;
       return JsonConvert.SerializeObject(state);
    }
    

    最终编辑:这绝对是您想要做的吗?我会非常犹豫是否将这样的代码放到野外。

    【讨论】:

    • 谢谢!但是你的代码仍然假设它是一个 IUserActor,我怎样才能让它动态呢?
    • 我已将其更新为投射到 IActor 可以吗?你说 IUserActor 继承自 IActor 对吧?你现在可以传入任何继承自 IActor 的接口的名称,它会工作
    • 可以,但我需要能够调用“AdminGetStateJson”,因为它在每个接口中单独实现。 IActor 不可修改。我猜我可以使用 GetMethod("AdminGetStateJson") 之类的东西并调用它,但我不确定应该在哪种类型上使用它?
    • 确实,您可以在您在那里解析的类型上使用它(我的答案中的变量“interfaceType”)。你会做 interfaceType.GetMethod("AdminGetStateJson")。我不确定它如何与 async 和 await 一起玩。没试过。
    • 我已经更新了我的答案以找到带有反射的“AdminGetStateJson”方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多