我在Azure中使用Service Fabric,并像这样设置一个代理:
var proxy = ActorProxy.Create<T>(actorId);
其中T必须指定为我所调用的actor的接口。
假设我有一个字符串形式的接口名:var interfaceName = "IUserActor";
是否有办法通过这个字符串名称来实例化泛型类型?如果有,如何通过字符串名称调用给定接口中指定的方法?
所有的actor接口都继承自IActor,它是Service Fabric的一部分。
现在我明白了这是不推荐的,关键是能够从测试和管理目的访问给定参与者的参与者状态。在这种情况下,速度是无关紧要的,所以任何反射方法都可以。
那么,一个基本的用法示例,不使用动态接口名称:public async Task<string> AdminGetState(ActorId actorId, string interfaceName){
var proxy = ActorProxy.Create<IUserActor>(actorId);
var state = await proxy.AdminGetStateJson();
return JsonConvert.SerializeObject(state);
}
这不美观也不高效,但是您可以使用反射…
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);
}
最终编辑:这一定是你想做的吗?我很犹豫是否要把这样的代码放到外面