以前没研究过这种问题。现在想学习一下。 以前见过一个样板工程很经典,但是当时没备份,现在找不到了。
我简单介绍下。
那是一个服务系统,其实是一个服务平台,内部包括了很多的服务功能。
该系统启动时会加载N多插件类。(包括规则脚本,功能脚本,动作脚本,配置信息等等)这些脚本文件其实都是 C#的CS代码文件。 这个系统提供一套公开的API或者类和方法。然后允许你按照它的要求娶继承,去重载,去扩充一些类或者接口,直接写在CS文件里,方到制定的目录里。
系统启动的时候会先编译这些CS文件,并加载到程序内部。然后开始服务。
再系统执行期间,你仍然可以继续编写和修改CS文件,其中相当大的一部分CS文件并不需要重新启动系统生效。只要再系统的控制台输入指令,RELOAD XXXXX 这样的指令, XXXXX类型的CS文件就会被重新编译和加载。直接实现功能的调整。现在很想学习这方面的技术。补充: 对此技术本人很陌生,希望懂行的大侠们别只是说娶看MSDN,或者说去看什么什么说明。还是希望您能指点下方向和方法和流程,最好能有些理论上的介绍和讲解。。谢谢啦。
我简单介绍下。
那是一个服务系统,其实是一个服务平台,内部包括了很多的服务功能。
该系统启动时会加载N多插件类。(包括规则脚本,功能脚本,动作脚本,配置信息等等)这些脚本文件其实都是 C#的CS代码文件。 这个系统提供一套公开的API或者类和方法。然后允许你按照它的要求娶继承,去重载,去扩充一些类或者接口,直接写在CS文件里,方到制定的目录里。
系统启动的时候会先编译这些CS文件,并加载到程序内部。然后开始服务。
再系统执行期间,你仍然可以继续编写和修改CS文件,其中相当大的一部分CS文件并不需要重新启动系统生效。只要再系统的控制台输入指令,RELOAD XXXXX 这样的指令, XXXXX类型的CS文件就会被重新编译和加载。直接实现功能的调整。现在很想学习这方面的技术。补充: 对此技术本人很陌生,希望懂行的大侠们别只是说娶看MSDN,或者说去看什么什么说明。还是希望您能指点下方向和方法和流程,最好能有些理论上的介绍和讲解。。谢谢啦。
你说的功能在CodeDOM中都可以实现,不过如果有已经实现好的模板,那当然是最好的。
使用CodeDOM,编译代码为dll,然后加载,接着通过反射来做调用执行期间的修改,可以通过命令或者操作来卸载dll,然后重新编译并加载 就可以了
MSDN看着很散
FileInfo sourceFile = new FileInfo(sourceFileName);
CodeDomProvider provider = null;
bool compileOk = false; provider = new Microsoft.CSharp.CSharpCodeProvider();
if (provider != null)
{
String asmName= String.Format(@"{0}\{1}.dll",
System.Environment.CurrentDirectory,
sourceFile.Name.Replace(".", "_")); CompilerParameters cp = new CompilerParameters(); // 生成类库
cp.GenerateExecutable = false; // 指定输出文件名
cp.OutputAssembly = asmName;
// 保存为文件
cp.GenerateInMemory = false;
// 不将编译警告作为错误
cp.TreatWarningsAsErrors = false;
// 编译
CompilerResults cr = provider.CompileAssemblyFromFile(cp,
sourceName);
if(cr.Errors.Count <1)
{
// 加载
Assembly asm = Assembly.Load(asmName);
//调用
//DoSomething();
}
}引用系统之外的dll只需要将其放到bin下面或者应用程序目录下就好了
这是不是还要编排他们的编译顺序? 如果CS文件里边应该的编译顺序我不知道怎么办?(比如是别人写的CS)
可以同时指定一堆CS文件,然后让NET自己选择顺序不?
CompilerParameters options,
params string[] sources
)
。net好玩的东西都在这里了
慢慢看吧很详细
http://topic.csdn.net/u/20080913/04/801f558c-1068-4751-88ca-e883298cf1b5.html
个人认为并不低,损失一点效率换取极大的灵活性,还是赚的,采用合适的策略,可以尽可能少的用到反射,避免大量反射调用带来的性能损失既然是继承自接口或基类,那么只需要在创建工厂的时候用到一次反射,然后将工厂保存起来,之后通过工厂来得到实例,无需放射,其他时间都是通过基类直接调用实例方法即可,同样无需反射for example//classes that need dynamic compile:
public interface IBase
{
void A();
}public class implementA:IBase
{
void A()
{
//do somthing..
}
}//factories:
public interface IFactory
{
IBase CreateInstance();
} public class implementAFac:IFactory
{
IBase CreateInstance()
{
return new implementA();
}
}//client:
//get factory instance by reflection
IFactory fac= Activator.CreateInstance("company.product.implementAFac") as IFactory;
//get instance as base class type
IBase base = fac.GetInstance();
//call
base.A();
至于多个编译顺序没研究过,因该可以通过一定的规则组合在一起
现成的C#脚本引擎
把C#本身当做脚本,又当做宿主语言,超牛!