Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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# 隐式创建位于依赖dll中的类的实例_C#_.net_Vb.net - Fatal编程技术网

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);