盼高手解答: 如何在C#中实现动态调用未知控件???
可能题目有点模糊,我要实现的功能大概如下:
假设有一个用C#写的并编译成功的控件库"SuperWarningBox.dll",要在另外一个C#的Windows Forms程序MyForm中调用该控件库中的方法,但是MyForm程序编译的时候并不知道要调用此控件
我的设想是MyForm程序运行时通过读取一个确定的配置文件(例如一个文本或XML文件)得知存在一个名字叫"SuperWarningBox.dll"的控件库,并且从配置文件中得知该控件中存在的所有可以供调用的方法的名称、参数个数和类型,并按照需要从中选择一个方法并用适当的参数调用此方法
如何实现上面的功能呢?? 我现在要做一个OA系统,如果无法实现上述功能拿我就彻底没辙了!!!
急切盼望高手做答!!!!!!!!!!!! 一定要用C#实现啊!!!!!!
如果解答满意,立即送上200分!
假设有一个用C#写的并编译成功的控件库"SuperWarningBox.dll",要在另外一个C#的Windows Forms程序MyForm中调用该控件库中的方法,但是MyForm程序编译的时候并不知道要调用此控件
我的设想是MyForm程序运行时通过读取一个确定的配置文件(例如一个文本或XML文件)得知存在一个名字叫"SuperWarningBox.dll"的控件库,并且从配置文件中得知该控件中存在的所有可以供调用的方法的名称、参数个数和类型,并按照需要从中选择一个方法并用适当的参数调用此方法
如何实现上面的功能呢?? 我现在要做一个OA系统,如果无法实现上述功能拿我就彻底没辙了!!!
急切盼望高手做答!!!!!!!!!!!! 一定要用C#实现啊!!!!!!
如果解答满意,立即送上200分!
...全文
请发表友善的回复…
发表回复
syinter 2002-11-12
- 打赏
- 举报
5drush,谢了,
请告诉我相关的MSDN地址吗,
得知后我马上给200分! 绝不食言
请告诉我相关的MSDN地址吗,
得知后我马上给200分! 绝不食言
5drush 2002-11-12
- 打赏
- 举报
Microsoft .NET 框架 SDK 快速入门、教程和示例中的“反射调用”
5drush 2002-11-10
- 打赏
- 举报
下面这段代码是上面调用的dll文件的代码(tester.dll):
using System;
using System.Windows.Forms;
// Some test methods to try from the Invoke sample
public class SomeType {
public static double AddTwoDoubles(double num1, double num2){
return num1 + num2;
}
public DialogResult ShowMessage(String message){
return MessageBox.Show(message);
}
public DialogResult ShowMessage(String message, String caption){
return MessageBox.Show(message, caption);
}
public DialogResult ShowMessage(String message, String caption, int style){
return MessageBox.Show(message, caption, (MessageBoxButtons)style);
}
}
using System;
using System.Windows.Forms;
// Some test methods to try from the Invoke sample
public class SomeType {
public static double AddTwoDoubles(double num1, double num2){
return num1 + num2;
}
public DialogResult ShowMessage(String message){
return MessageBox.Show(message);
}
public DialogResult ShowMessage(String message, String caption){
return MessageBox.Show(message, caption);
}
public DialogResult ShowMessage(String message, String caption, int style){
return MessageBox.Show(message, caption, (MessageBoxButtons)style);
}
}
5drush 2002-11-10
- 打赏
- 举报
晕,我那个只是MSDN上的例子呀,给你参考一下Reflection的用法的,你要改一下撒。。。
再给你贴一段,同样是MSDN上的例子,结合文档弄明白再用,不要照抄,OK?
using System;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
public class App {
public static void Main(String[] args) {
if (args.Length < 3) {
Usage();
return;
}
Assembly assembly;
Type type;
try{
// Load the requested assembly and get the requested type
assembly = Assembly.LoadFrom(args[0]);
type = assembly.GetType(args[1], true);
}catch(FileNotFoundException){
Console.WriteLine("Could not load Assembly: \"{0}\"", args[0]);
return;
}catch(TypeLoadException){
Console.WriteLine(
"Could not load Type: \"{0}\"\nfrom assembly: \"{1}\"",
args[1], args[0]);
return;
}
// Get the methods from the type
MethodInfo[] methods = type.GetMethods();
if(methods == null){
Console.WriteLine("No Matching Types Found");
return;
}
// Make a new array that holds only the args for the call
String[] newArgs = new String[args.Length-3];
if(newArgs.Length != 0){
Array.Copy(args, 3, newArgs, 0, newArgs.Length);
}
// Try each method for a match
StringBuilder failureExcuses = new StringBuilder();
foreach(MethodInfo m in methods){
Object obj = null;
try{
obj = AttemptMethod(type, m, args[2], newArgs);
}catch(CustomException e){
failureExcuses.Append(e.Message+"\n");
continue;
}
// If we make it this far without a throw, our job is done!
Console.WriteLine(obj);
return;
}
Console.WriteLine("Suitable method not found!");
Console.WriteLine("Here are the reasons:\n"+failureExcuses);
}
// Checks a method for a signature match, and invokes it if there is one
private static Object AttemptMethod(Type type,
MethodInfo method, String name, String[] args){
// Name does not match?
if(method.Name != name){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Name Doesn't Match!");
}
// Wrong number of parameters?
ParameterInfo[] param = method.GetParameters();
if(param.Length != args.Length){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Signatures Don't Match!");
}
// Ok, can we convert the strings to the right types?
Object[] newArgs = new Object[args.Length];
for(int index = 0; index < args.Length;index++){
try{
newArgs[index] = Convert.ChangeType(args[index],
param[index].ParameterType);
}catch(Exception e){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Argument Conversion Failed", e);
}
}
// We made it this far, lets see if we need an instance of this type
Object instance = null;
if(!method.IsStatic){
instance = Activator.CreateInstance(type);
}
// ok, let's invoke this one!
return method.Invoke(instance, newArgs);
}
// Print usage
private static void Usage() {
Console.WriteLine(
"Usage:\n" +
" Invoke [Assembly] [Type] [Method] [Parameters...]");
}
class CustomException:Exception{
public CustomException(String m):base(m){}
public CustomException(String m, Exception n):base(m,n){}
}
}
再给你贴一段,同样是MSDN上的例子,结合文档弄明白再用,不要照抄,OK?
using System;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
public class App {
public static void Main(String[] args) {
if (args.Length < 3) {
Usage();
return;
}
Assembly assembly;
Type type;
try{
// Load the requested assembly and get the requested type
assembly = Assembly.LoadFrom(args[0]);
type = assembly.GetType(args[1], true);
}catch(FileNotFoundException){
Console.WriteLine("Could not load Assembly: \"{0}\"", args[0]);
return;
}catch(TypeLoadException){
Console.WriteLine(
"Could not load Type: \"{0}\"\nfrom assembly: \"{1}\"",
args[1], args[0]);
return;
}
// Get the methods from the type
MethodInfo[] methods = type.GetMethods();
if(methods == null){
Console.WriteLine("No Matching Types Found");
return;
}
// Make a new array that holds only the args for the call
String[] newArgs = new String[args.Length-3];
if(newArgs.Length != 0){
Array.Copy(args, 3, newArgs, 0, newArgs.Length);
}
// Try each method for a match
StringBuilder failureExcuses = new StringBuilder();
foreach(MethodInfo m in methods){
Object obj = null;
try{
obj = AttemptMethod(type, m, args[2], newArgs);
}catch(CustomException e){
failureExcuses.Append(e.Message+"\n");
continue;
}
// If we make it this far without a throw, our job is done!
Console.WriteLine(obj);
return;
}
Console.WriteLine("Suitable method not found!");
Console.WriteLine("Here are the reasons:\n"+failureExcuses);
}
// Checks a method for a signature match, and invokes it if there is one
private static Object AttemptMethod(Type type,
MethodInfo method, String name, String[] args){
// Name does not match?
if(method.Name != name){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Name Doesn't Match!");
}
// Wrong number of parameters?
ParameterInfo[] param = method.GetParameters();
if(param.Length != args.Length){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Signatures Don't Match!");
}
// Ok, can we convert the strings to the right types?
Object[] newArgs = new Object[args.Length];
for(int index = 0; index < args.Length;index++){
try{
newArgs[index] = Convert.ChangeType(args[index],
param[index].ParameterType);
}catch(Exception e){
throw new CustomException(method.DeclaringType + "." + method.Name + ": Argument Conversion Failed", e);
}
}
// We made it this far, lets see if we need an instance of this type
Object instance = null;
if(!method.IsStatic){
instance = Activator.CreateInstance(type);
}
// ok, let's invoke this one!
return method.Invoke(instance, newArgs);
}
// Print usage
private static void Usage() {
Console.WriteLine(
"Usage:\n" +
" Invoke [Assembly] [Type] [Method] [Parameters...]");
}
class CustomException:Exception{
public CustomException(String m):base(m){}
public CustomException(String m, Exception n):base(m,n){}
}
}
syinter 2002-11-10
- 打赏
- 举报
再补充一下,编译成"DynamicAssem.dll"也不行
syinter 2002-11-10
- 打赏
- 举报
5drush,不行啊!!!
我另外写了一段代码编译为类库文件"DynamicModule.dll" ,然后把DynamicModule.dll放在了你那段代码编译后的执行文件同一目录下,可是执行了你那段代码后仍然不能调用我写的这个库中的方法SimpleMethod()啊!!!
我写的代码如下:
using System;
namespace DynamicModule
{
public class ANonExistentType
{
public void SimpleMethod()
{
Console.WriteLine("TEST");
}
}
}
到底怎么搞的??
我另外写了一段代码编译为类库文件"DynamicModule.dll" ,然后把DynamicModule.dll放在了你那段代码编译后的执行文件同一目录下,可是执行了你那段代码后仍然不能调用我写的这个库中的方法SimpleMethod()啊!!!
我写的代码如下:
using System;
namespace DynamicModule
{
public class ANonExistentType
{
public void SimpleMethod()
{
Console.WriteLine("TEST");
}
}
}
到底怎么搞的??
snewxf 2002-11-10
- 打赏
- 举报
对呀·我楼上两位说得对!同意!
sdsxc 2002-11-10
- 打赏
- 举报
使用反射:
Assembly SampleAssembly = Assembly.LoadFrom("e:\\ClsEquip.dll");
foreach(Type t in SampleAssembly.GetTypes())
{
MessageBox.Show(t.Name);
foreach(MethodInfo Method in t.GetMethods())
{
MessageBox.Show(Method.Name);
ParameterInfo[] Params = Method.GetParameters();
foreach (ParameterInfo Param in Params)
{
MessageBox.Show("Param=" + Param.Name.ToString());
MessageBox.Show(" Type=" + Param.ParameterType.ToString());
MessageBox.Show(" Position=" + Param.Position.ToString());
MessageBox.Show(" Optional=" + Param.IsOptional.ToString());
}
}
}
大体思路就是这样,你可以参考一下
Assembly SampleAssembly = Assembly.LoadFrom("e:\\ClsEquip.dll");
foreach(Type t in SampleAssembly.GetTypes())
{
MessageBox.Show(t.Name);
foreach(MethodInfo Method in t.GetMethods())
{
MessageBox.Show(Method.Name);
ParameterInfo[] Params = Method.GetParameters();
foreach (ParameterInfo Param in Params)
{
MessageBox.Show("Param=" + Param.Name.ToString());
MessageBox.Show(" Type=" + Param.ParameterType.ToString());
MessageBox.Show(" Position=" + Param.Position.ToString());
MessageBox.Show(" Optional=" + Param.IsOptional.ToString());
}
}
}
大体思路就是这样,你可以参考一下
5drush 2002-11-10
- 打赏
- 举报
呵呵,看在200分的面子上:),再贴一个例子:
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Runtime.Remoting;
class App {
static Assembly TypeResolveHandler(Object sender, ResolveEventArgs e) {
Console.WriteLine("In TypeResolveHandler");
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DynamicAssem";
// Create a new assembly with one module
AssemblyBuilder newAssembly =
Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder newModule = newAssembly.DefineDynamicModule("DynamicModule");
// Define a public class named "ANonExistentType" in the assembly.
TypeBuilder myType = newModule.DefineType("ANonExistentType", TypeAttributes.Public);
// Define a method on the type to call
MethodBuilder simpleMethod = myType.DefineMethod("SimpleMethod", MethodAttributes.Public, null, null);
ILGenerator il = simpleMethod.GetILGenerator();
il.EmitWriteLine("Method called in ANonExistentType");
il.Emit(OpCodes.Ret);
// Bake the type
myType.CreateType();
return newAssembly;
}
static void Main() {
// Hook up the event handler
Thread.GetDomain().AssemblyResolve +=new ResolveEventHandler(App.TypeResolveHandler);
// Find a type that should be in our assembly but isn't
ObjectHandle oh = Activator.CreateInstance("DynamicAssem", "ANonExistentType");
Type mt = oh.Unwrap().GetType();
// Construct an instance of a type
Object objInstance = Activator.CreateInstance(mt);
// Find a method in this type and call it on this object
MethodInfo mi = mt.GetMethod("SimpleMethod");
mi.Invoke(objInstance, null);
}
}
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Runtime.Remoting;
class App {
static Assembly TypeResolveHandler(Object sender, ResolveEventArgs e) {
Console.WriteLine("In TypeResolveHandler");
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DynamicAssem";
// Create a new assembly with one module
AssemblyBuilder newAssembly =
Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder newModule = newAssembly.DefineDynamicModule("DynamicModule");
// Define a public class named "ANonExistentType" in the assembly.
TypeBuilder myType = newModule.DefineType("ANonExistentType", TypeAttributes.Public);
// Define a method on the type to call
MethodBuilder simpleMethod = myType.DefineMethod("SimpleMethod", MethodAttributes.Public, null, null);
ILGenerator il = simpleMethod.GetILGenerator();
il.EmitWriteLine("Method called in ANonExistentType");
il.Emit(OpCodes.Ret);
// Bake the type
myType.CreateType();
return newAssembly;
}
static void Main() {
// Hook up the event handler
Thread.GetDomain().AssemblyResolve +=new ResolveEventHandler(App.TypeResolveHandler);
// Find a type that should be in our assembly but isn't
ObjectHandle oh = Activator.CreateInstance("DynamicAssem", "ANonExistentType");
Type mt = oh.Unwrap().GetType();
// Construct an instance of a type
Object objInstance = Activator.CreateInstance(mt);
// Find a method in this type and call it on this object
MethodInfo mi = mt.GetMethod("SimpleMethod");
mi.Invoke(objInstance, null);
}
}
yarshray 2002-11-10
- 打赏
- 举报
http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx
装配件assembly
装配件assembly
5drush 2002-11-10
- 打赏
- 举报
你有救了,用Reflection可以达到你的目的,具体如何用可以去看看MSDN
syinter 2002-11-10
- 打赏
- 举报
我要在程序运行的时候动态调用啊,总不可能要把源代码也当软件一起发布出去吧
cambest 2002-11-10
- 打赏
- 举报
你可以在命令行下编译:
csc yours.cs *.cs /r:SuperWarningBox.dll
在vs里面也可以通过选项来修改添加库。
csc yours.cs *.cs /r:SuperWarningBox.dll
在vs里面也可以通过选项来修改添加库。
syinter 2002-11-10
- 打赏
- 举报
不好意思,忘记改分数了,不过我得到正确解答后一定再送上200分!!!
高手一定要帮我啊
高手一定要帮我啊