Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以在“中发出现有的实现吗?”;“临时”;装配_C#_Reflection_Reflection.emit - Fatal编程技术网

C# 我可以在“中发出现有的实现吗?”;“临时”;装配

C# 我可以在“中发出现有的实现吗?”;“临时”;装配,c#,reflection,reflection.emit,C#,Reflection,Reflection.emit,以下面的C代码为例 我想生成一个包含lib.foo.A.GetNumber()功能的程序集,存储它,然后动态加载并执行它。 为了实现这一点,我需要一个程序,它可以跟踪所有必需的依赖项(如下所列),并在一个存储程序集中发出它们(包括它们的实现(!) * lib.foo.A(int) * lib.foo.A.getNumber() * lib.foo.A.calculateNumer() * lib.bar.B.ProduceNumber() 能做到吗?怎么做 如果有人想知道,我想构建一个

以下面的C代码为例

我想生成一个包含
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;
    }
}
然而,我必须强调,你可能不应该这样做

至于原来的问题:

我会非常小心地传输和执行任意代码,尤其是在生产环境中;安全漏洞的可能性很大,主要是通过注入途径。例如,如果您接受上面的一个建议,只需快速浏览源代码即可动态执行,那么几乎没有人会阻止您向“给我运行的代码”服务中注入什么内容

你真的需要在这里详细说明你的确切需求,才能真正想出一个“好”的解决方案,因为有多种方法可以实现相同的基本想法:

  • 如前所述,将实际的源代码传递给服务以加载/编译/执行,可能是在“沙箱”中,以实现某些方面的安全性/保护

  • 将共享插件/程序集中的所有可执行代码路径分发给所有远程服务器,并将执行器代码简化为单个“DoWork”方法调用(即,将插件中的所有详细信息打包)

  • 拼凑出一个粗略的DSL或其他类型的伪语言,受限于它能做什么/不能做什么,并传递源代码

  • 依赖.NET远程处理:通过代理远程调用远程对象上程序集中的方法


以源代码形式保留所有“可传输代码”,这样您就不需要通过反射“恢复”它。。。您可以将其传输到任何您喜欢的地方进行编译…那么为什么不使用不可卸载的插件呢?因此,机器B总是可以加载/卸载它们,而您所需要的只是一个插件主机,它能够完成这些工作(按名称调用插件的方法)。这听起来很合理:将整个程序集(及其依赖项)从机器a传输到机器B,将其加载到AppDomain并按名称调用方法。我同意您的一般安全顾虑,但我的系统将在物理隔离的网络上运行。建议的系统将用于测试分布式应用程序黑盒样式;传输的代码包含测试指令。
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