C# - 在反射中使用C ++ COM dll时出现异常 [英] C# - Exception when C++ COM dll's used in reflection

查看:96
本文介绍了C# - 在反射中使用C ++ COM dll时出现异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每当我在C#中通过反射技术调用支持的COM dll时,它就会给出"调用目标抛出异常。"
$


我的代码:
$


公共类ExecuteAssembly {IAssembly objIAssembly = new Xml_Operations.XmlRetrive();



  ;   public void StartExecution()

    {

       试试
        {

           输入classType = LoadDll();
$


            //创建类计算器的实例

            // object classInstance = Activator.CreateInstance(classType);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; 动态classInstance =(动态)Activator.CreateInstance(classType);  &NBSP; < -
ERROR GETS FIRED


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; classInstance.Visible = true;



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //获取有关方法的信息:public

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; MethodInfo methodCall = classType.GetMethod(objIAssembly.MethodName);



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; ParameterInfo [] parameters = methodCall.GetParameters();
$


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; objIAssembly.MethodOutput = methodCall.Invoke(classInstance,objIAssembly.ParametersArray);



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; Xml_Operations.XmlStore.OutputToXmlFile(objIAssembly);

  &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; &NBSP; &NBSP; catch(例外情况)

  &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; Console.WriteLine(ex.Message);

  &NBSP; &NBSP; &NBSP; }


  &NBSP; }


  &NBSP;私人类型LoadDll()

  &NBSP; {

  &NBSP; &NBSP; &NBSP; string [] dirSplit = objIAssembly.DllPath.Split('\\');

  &NBSP; &NBSP; &NBSP; string dllName = dirSplit [dirSplit.Length - 1] .Substring(0,dirSplit [dirSplit.Length - 1] .Length - 4); ;

  &NBSP; &NBSP; &NBSP; int count = dirSplit [dirSplit.Length - 1] .Count();

  &NBSP; &NBSP; &NBSP; string dirPath = objIAssembly.DllPath.Substring(0,(objIAssembly.DllPath.Length - count));
$


  &NBSP; &NBSP; &NBSP; var files = Directory.GetFiles(dirPath," * .dll");

  &NBSP; &NBSP; &NBSP;输入[]类型;

  &NBSP; &NBSP; &NBSP;输入classType = null;

  &NBSP; &NBSP; &NBSP; foreach(文件中的var文件)

  &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;试试
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; types = Assembly.LoadFrom(file).GetTypes();



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; if(types [0] .AssemblyQualifiedName.Contains(dllName))

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; classType = types [0];

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;抓住
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;继续;&NBSP; //无法加载为.NET程序集,因此请忽略

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; return classType;

  &NBSP; }
}

Whenever my supporting COM dll's is called through reflection technique in C#, It gives me "Exception has been thrown by the target of an invocation."

My Code:

public class ExecuteAssembly { IAssembly objIAssembly = new Xml_Operations.XmlRetrive();

    public void StartExecution()
    {
        try
        {
            Type classType = LoadDll();

            // create instance of class Calculator
            //object classInstance = Activator.CreateInstance(classType);
            dynamic classInstance = (dynamic) Activator.CreateInstance(classType);    <-- ERROR GETS FIRED
            classInstance.Visible = true;

            // get info about method: public
            MethodInfo methodCall = classType.GetMethod(objIAssembly.MethodName);

            ParameterInfo[] parameters = methodCall.GetParameters();

            objIAssembly.MethodOutput = methodCall.Invoke(classInstance, objIAssembly.ParametersArray);

            Xml_Operations.XmlStore.OutputToXmlFile(objIAssembly);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

    private Type LoadDll()
    {
        string[] dirSplit=objIAssembly.DllPath.Split('\\');
        string dllName = dirSplit[dirSplit.Length - 1].Substring(0, dirSplit[dirSplit.Length - 1].Length - 4); ;
        int count = dirSplit[dirSplit.Length - 1].Count();
        string dirPath = objIAssembly.DllPath.Substring(0, (objIAssembly.DllPath.Length - count));

        var files = Directory.GetFiles(dirPath ,"*.dll");
        Type[] types;
        Type classType = null;
        foreach (var file in files)
        {
            try
            {
                types = Assembly.LoadFrom(file).GetTypes();

                if (types[0].AssemblyQualifiedName.Contains(dllName))
                    classType = types[0];
            }
            catch
            {
                continue;  // Can't load as .NET assembly, so ignore
            }
        }

        return classType;
    }
}

推荐答案

反射旨在与.NET对象一起使用。虽然COM对象可能作为.NET对象公开,但它们实际上是基础COM对象的包装器。甚至调试器通常也无法提供有关它们的有用信息。
对COM对象使用反射通常不会很好。

Reflection is designed to work with .NET objects. While COM objects may be exposed as .NET objects, they are actually wrappers around the underlying COM object. Even the debugger is generally unable to provide much useful information about them. Using reflection against a COM object generally isn't going to work out well.

但复合这是你尝试使用动态的事实。动态实际上只不过是一本美化的字典。我甚至不知道它是否可以正常使用COM对象。但问题是你在这里不需要动态。 Activator.CreateInstance
返回一个对象,反射可以解决这个问题。所以你根本不需要动态。但至于反射是否会对COM对象有效,我对此表示怀疑。您将看到COM包装器成员,而不是COM接口。 COM使用QueryInterface工作。
当您从COM对象请求接口时,您可能会获得另一个对象。反射不适用于那种界面。

But compounding this is the fact that you're trying to use dynamic. Dynamic is really nothing more than a glorified dictionary. I don't even know if it can properly work with COM objects. But the thing is that you don't need dynamic here. Activator.CreateInstance returns an object and reflection can work off that. So you don't need dynamic at all. But as for whether reflection will work against the COM object, I doubt it. You'll see the COM wrapper members, not the COM interface. COM works by using QueryInterface. When you request an interface from the COM object you'll potentially get a different object. Reflection isn't going to work with that kind of interface.

对于要在运行时发现内容的COM,您需要使用IDispatch,它确实提供了获得成员(并称之为成员)的必要基础设施。这是您想要使用COM对象的方式。如果COM对象没有
实现IDispatch,那么它就不能以这种方式工作。

For COM, where you want to discover things at runtime, you need to be using IDispatch which does provide the necessary infrastructure to get the members (and call them). This is how you'd want to work with a COM object. If the COM object doesn't implement IDispatch then it isn't designed to work this way.

你也可以考虑只使用COM对象它支持特定的COM接口。在这种情况下,您可以使用转换为COM接口的常规编码实践,然后像使用任何.NET对象一样使用接口成员。

You might also consider only working with a COM object if it supports a specific COM interface. In that case you can use the normal coding practice of converting to the COM interface and then use the interface members like you would any .NET object.


这篇关于C# - 在反射中使用C ++ COM dll时出现异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆