用下面的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调用所需的方法,该方法在这个新的汇编中实现。
注意-这不是一个真正的答案,更多的是一个挑剔的纠正(各种).
当你说"因为序列化委托是不可能的",这不是严格正确,尽管我不建议这样做。下面的示例代码有效地"序列化"一个委托:
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;
}
}
输出:Func`2 was serialized to 978 bytes
I was called with 1, returning 2
然而,我必须强调,您可能不应该这样做。:) 对于最初的问题:
我会非常小心地传输和执行任意代码,特别是在生产环境中;安全漏洞的可能性相当大,主要是通过注入路径。举个例子,如果你采纳了上面的建议之一,并且只是通过源代码来动态地执行,那么就很难阻止有人向你的"给我代码来运行"服务中注入什么。
你真的需要在这里说出你的确切需求,才能真正想出一个"好的"解决方案,因为有多种方法可以实现相同的基本想法:
如前所述,将实际的源代码传递给服务以加载/编译/执行,可能在"沙盒"中用于某些安全/保护
将所有可执行代码路径分布在一个共享的插件/程序集中,由一些受信任的进程推送到所有远程服务器,并将执行代码减少到单个"DoWork"方法调用(即,将所有细节包装在插件中)
拼凑一个粗略的DSL或其他类型的伪语言,限制它能做什么/不能做什么,并传递源代码。
依赖于。net远程:实际上是通过代理在远程对象上远程调用程序集中的方法。