C# 隐式创建位于依赖dll中的类的实例
假设您正在开发一个名为C# 隐式创建位于依赖dll中的类的实例,c#,.net,vb.net,C#,.net,Vb.net,假设您正在开发一个名为“ThirdParty.DLL”的第三方DLL,它有一个名为JustTryToInstanceMe的类。假设您的客户有一个EXE,它引用了“ThirdParty.dll”,或者该EXE没有引用“ThirdParty.dll”,但是如果以某种方式请求,EXE可以在路径中找到“ThirdParty.dll”。您无法控制EXE,因为您是“Thirdparty.dll”的供应商,只能修改dll的功能。编写EXE的客户同意引用您的DLL或将您的DLL放入路径中。没别的了 运行EXE时
“ThirdParty.DLL”
的第三方DLL,它有一个名为JustTryToInstanceMe
的类。假设您的客户有一个EXE,它引用了“ThirdParty.dll”
,或者该EXE没有引用“ThirdParty.dll”
,但是如果以某种方式请求,EXE可以在路径中找到“ThirdParty.dll”
。您无法控制EXE,因为您是“Thirdparty.dll”
的供应商,只能修改dll的功能。编写EXE的客户同意引用您的DLL或将您的DLL放入路径中。没别的了
运行EXE时,是否有方法在不显式使用new
或调用静态/共享方法/字段/属性的情况下实例化justTryToInstanceMe
也许只是以某种方式使用静态/共享构造函数?可能在
AssemblyLoad()
事件上?也许使用注册表?启动过程?正在寻找想法…我知道的最接近的方法是动态加载程序集,然后从您创建的类的实例中调用方法
下面是代码的c#模板:
//add using for system.reflection
String className = "[NAME OF CLASS WITH FULL NAMESPACE GOES HERE]";
String methodName = "[METHOD NAME GOES HERE]"
String dllPath = "[FILE PATH FOR DLL GOES HERE]";
Assembly assembly = Assembly.LoadFile(dllPath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
//optionally set up parameters here
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
例如,我可以创建这样一个类(我知道,它是VB,但后面是C#)
然后在编译之后,我可以使用C#中的以下代码来执行我认为您所要求的操作:
//using system.reflection
String className = "mytestlibrary.my_class";
String dllPath = "...mytestlibrary.dll";
String methodName = "gethello";
Assembly assembly = Assembly.LoadFile(dllPath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
//result is "hello world"
现在,如果你想做同样的事情,但是使用一个已经编译的EXE文件,那么代码几乎没有什么不同,但是你需要创建一个桌面/控制台应用程序来外壳其他可执行文件,并正确地命名你的DLL。因此,在你的应用程序中,添加以下代码从EXE中引用的DLL中获取一个类的实例
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
String className = "My_Class";
String ExePath = "[PATH TO EXE]";
String methodName = "gethello";
Assembly assembly = Assembly.LoadFile(ExePath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);
您也可以将程序集动态加载到EXE中,但这有点棘手,因此,除非您真的需要将DLL动态加载到EXE中,否则我暂时不讨论这个问题。通过研究,我发现这个问题的简单答案是这是不可能的。简短的回答是为了要加载的DLL中的类该类需要被某个对象引用。如果某个DLL仅在路径中就能够自行加载,这将带来各种安全问题。您考虑过吗?如果JustTryToInstanceMe是一个静态类,则在尝试加载时会自动调用私有静态构造函数使用该类。您只需要在代码文件中使用一个using语句(C#)。
使用第三方;
这两个建议都假设EXE知道“justTryToInstanceMe”。如问题中所述,情况并非如此。EXE可以找到“ThirdParty.dll”在路径中,如果clr指示它查找,但EXE中没有直接引用“JustTryToInstanceMe”的代码@RadioSpace-你确定最后一部分是真的吗?如果不确定,我会想象编译器会足够聪明,知道类型实际上没有被使用,因此不会调用静态构造函数。只是好奇。你怎么知道你想要实例化什么类?你有“JustTryToInstanceMe”吗至少作为字符串?您可以枚举程序集中的所有类型,并使用反射创建实例:这种反射方法有意义,但您需要将其放入EXE。这是不允许的。您不能修改EXE,您只能修改进入DLL的代码。啊,我得到了它。我将运行一个测试并查看结果是什么。@Denis,您实际上可以将程序集添加到已编译的可执行文件中,并使用这些新程序集修改程序的执行方式。您不能更改代码,但在某种程度上您可以覆盖它。顺便说一句,自上次编辑以来有任何反馈吗?如果给我同样的问题,上面的代码就是我将如何处理它的。请告诉我,如果我能提供更多帮助,请告诉我。我将更新我的答案到规范。-干杯:)
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
String className = "My_Class";
String ExePath = "[PATH TO EXE]";
String methodName = "gethello";
Assembly assembly = Assembly.LoadFile(ExePath);
Type type = assembly.GetType(className);
MethodInfo method = type.GetMethod(methodName);
object context = Activator.CreateInstance(type);
object[] parameters = new object[0];
String result = (String) method.Invoke(context, parameters);