C# 我可以在“中发出现有的实现吗?”;“临时”;装配
以下面的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() 能做到吗?怎么做 如果有人想知道,我想构建一个
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远程处理:通过代理远程调用远程对象上程序集中的方法
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