一种处理多个代表类型的通用方法

时间:2016-09-14 23:38:20

标签: c# reflection

我正在开发一个项目,允许客户端在服务器上为其特定实例调用远程函数。基本上,当客户端连接时,它将获得自己的共享类实例,然后客户端将使用方法返回类型的名称和参数+它们的预期类型来调用服务器。

我正在进行的方式是创建一个Prototypes类,并在其中创建Delegates来表示Server的共享类中的Method原型。

  • 子问题:最好的方法是什么?我正在使用Delegates,但我不是双重声明的粉丝,因为它实际上是一个原型。接口是我想要的,但我可以找到一个很好的方法来创建它的实例,因为我不确定Prototype类将包含什么。

我将处理所有这些的方式是当客户端连接到服务器时,客户端将遍历Prototypes类并获取所有Fields,然后它将尝试将所有Fields内部链接到一个泛型方法来处理任何函数被调用后,该函数将获得它声明的返回类型&参数信息等,然后将其发送到服务器。

我的第一个想法是使用

params object[] param

但是,如果我说喂它,那么Delegate.CreateDelegate会在运行时出错:

public delegate string TestDelegate(string s1, string s2, string[] s3);

public TestDelegate Test;

但是,如果我创建了所有委托链接回的方法的多个重载,那么它可以正常工作:

    public T handleFunc<T>(object param)
    {
        Console.WriteLine(param as string);
        return default(T);
    }

    public T handleFunc<T>(object param, object param2)
    {
        Console.WriteLine(param as string);
        return default(T);
    }

    public T handleFunc<T>(object param, object param2, object param3)
    {
        Console.WriteLine((param3 as string[])[0]);
        return default(T);
    } 

这是我将代理链接到handleFunc方法的当前代码:

    private void ValidatePrototypes()
    {
        var fields = typeof(Prototypes).GetFields();
        foreach (FieldInfo field in fields)
        {
            MethodInfo thisfield = field.FieldType.GetMethods()[0];

            ParameterInfo[] pi = thisfield.GetParameters();

            var handle = typeof(Client).GetMethod("handleFunc", Array.ConvertAll(pi, s => s.ParameterType));

            var lambda = handle.MakeGenericMethod(thisfield.ReturnType);

            Delegate del = Delegate.CreateDelegate(field.FieldType, this, lambda);

            field.SetValue(Functions, del);
        }
        Console.WriteLine(Functions.Test("", "", new[] { "Hello" }));
    }

我实际上需要一个方法来任何可能的委托(或者最好的变体)链接到并能够从那里处理数据。

我感谢任何回复。

1 个答案:

答案 0 :(得分:0)

我认为这可以在不在运行时创建委托的情况下完成:

public interface IService {
    string Foo(int x);
}
public class ServerClass : IService {
    public string Foo(int x) {
        return x.ToString();
    }
}

public class ClientStub : IService {
    protected ITarget target;
    public ClientStub(ITarget target) {
        this.target = target;
    }
    public string Foo(int i) {
        return (string)target.Invoke(nameof(Foo), i);
    }
}

public interface ITarget {
    object Invoke(string methodName, params object[] args);
}

public class RemoteTarget : ITarget {
    public object Invoke(string methodName, params object[] args) {
        // send params over network and return response
    }
}

...

new ClientStub(new RemoteTarget()).Foo();

使用您的方法对此没有任何好处。他们通常在框架中执行的操作是它们在运行时使用反射发射实现ClientStub类,因此您不必手动编写它。