0

采用以下 C# 代码

namespace lib.foo {
  public class A {
    public A (int x) {}
    public int GetNumber() { return calculateNumber(); }
    private int calculateNumber() { return lib.bar.B.ProduceNumber(); }
    public void irrelevantMethod() {}
  }
}
namespace lib.bar {
  public class B {
    public static int ProduceNumber() { return something; }
    public void IrrelevantMethod() {}
  }
}

我想生成一个包含 的功能的程序集lib.foo.A.GetNumber(),存储它,然后动态加载它,然后执行它。
为了让它工作,我需要一个程序来跟踪所有必需的依赖项(如下所列),并在一个程序集中发出它们——包括它们的实现(!)——以进行存储。

 * lib.foo.A(int)
 * lib.foo.A.getNumber()
 * lib.foo.A.calculateNumer()
 * lib.bar.B.ProduceNumber()

可以做到吗?如何?

如果有人想知道,我想构建一个系统,让机器 A 告诉机器 B(使用 WCF)做什么。由于序列化代表是不可能的,我的计划是

1)将组件从机器 A 运输到 B,

2)将组件加载到机器 B 上,

3)让机器 A 指示机器 B 调用所需的方法,该方法在这个新程序集中实现。

4

1 回答 1

2

Note - this isn't really an answer, more of a nitpicking correction (of sorts)..

When you say "Since serializing delegates is impossible", this isn't strictly true, although I would NOT recommend doing it. This example code effectively "serializes" a delegate:

void Main()
{
    Func<int,int> dlgt = FuncHolder.SomeMethod;
    var ser = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
    byte[] buffer;
    using(var ms = new MemoryStream())
    {
        ser.Serialize(ms, dlgt);
        buffer = ms.ToArray();
    }
    Console.WriteLine("{0} was serialized to {1} bytes", dlgt.GetType().Name, buffer.Length);
    using(var ms = new MemoryStream(buffer))
    {
        dynamic whatzit = ser.Deserialize(ms);
        whatzit(1);
    }
}

[Serializable]
public struct FuncHolder
{
    public static int SomeMethod(int i)
    {
        Console.WriteLine("I was called with {0}, returning {1}", i, i+1);
        return i+1;
    }
}

Output:

Func`2 was serialized to 978 bytes
I was called with 1, returning 2

I must emphasize, however, that you probably shouldn't do this. :)

As for the original question:

I'd be very careful about transporting and executing arbitrary code, especially in a production environment; the potential for security breaches is considerable, mainly via injection routes. If you were to take, for example, one of the above suggestions and just blast over the source to execute dynamically, there's little stopping someone from injecting who-knows-what into your "Give me code to run" service.

You'd really need to spell out your exact needs here to really come up with a "good" solution, as there are multiple ways to accomplish the same basic idea:

  • as mentioned, pass actual source code to the service to load/compile/execute, potentially in a "sandbox" for some aspect of security/protection

  • distribute all executable code paths in a shared plugin/assembly which is pushed by some trusted process to all remote servers, and reduce your executor code to a single "DoWork" method invocation (i.e., wrap all the details inside the plugin)

  • Cobble together a rough DSL or other type of pseudo-language, restricted in what it can/can't do, and pass that source around.

  • rely on .NET remoting: actually go remotely call the methods in the assembly on a remote object via proxy.

于 2013-05-30T15:35:03.093 回答