我可以在"临时"中发出现有的实现吗?部件

时间:2013-05-30 14:35:03

标签: c# reflection reflection.emit

采用以下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调用所需的方法,该方法在这个新程序集中实现。

1 个答案:

答案 0 :(得分:2)

注意 - 这不是一个真正的答案,更多的是挑剔的纠正(各种各样)......

当您说“由于序列化代理是不可能的”时,这不是严格 true,尽管我不建议这样做。此示例代码有效地“序列化”了一个委托:

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远程处理:实际上是通过代理远程调用远程对象上程序集中的方法。