这是个类型转换的问题!解决了俺就可以回家过年啦 :(

时间:2022-03-16 01:06:05
Assembly a = Assembly.LoadFrom(@"D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll");
Type[] Types = a.GetTypes();
//下面省略了循环,因为我ClipsWrapper.dll程序集合里就一个类CClipsWrapper,并且是继承了IEngine这个接口的。
if(t.IsClass && !t.IsAbstract) 
{
//然后我本地项目也引用了这个接口IEngine
//可是运行到下面语句却报错了,说是类型转换出错
IEngine o = (IEngine)Activator.CreateInstance(t);
...
}
兄弟么,俺可不想带着问题回家过年啊,谢了

17 个解决方案

#1


use
Type[] myObjectArray= t.GetInterfaces();

to make sure IEngine is one of them

#2


不要在两个工程同时定义IEngine...

#3


刚才为了说明方便,其实我的D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll是用C++托管写的,而C++托管没有接口这一说,所以我单独做了一个抽象类IEngine(也是C++托管写的DLL),然后ClipsWrapper.dll里的类继承了这个抽象类。

然后象上面那样在C#里强制转换,可是不行,我在DEBUG单步跟的时候,显示o的Basetype确实是IEngine,可就是转不成!

我在想是不是因为我用的是C++托管抽象类的关系呢?

劳驾!

#4


how did you define your C++ interface? like
__gc __interface IMyInterface 

?

#5


不好意思,我不知道托管C++里还有接口这一说,我定义的是一个托管C++的虚函数来代替接口的:
// IEngine.h

using namespace System;

namespace IEngineSpace
{

public __gc class IEngine
{
public:
IEngine(void);
virtual ~IEngine(void);

virtual void reset()=0;

virtual void run()=0;
};
}
现面是CPP文件:
#include "StdAfx.h"
#include "IEngine.h"
#using <mscorlib.dll>

namespace IEngineSpace
{
IEngine::IEngine(void)
{
}

IEngine::~IEngine(void)
{
}

}
我这样写我觉得也没什么问题啊?

不过兄弟你提醒了俺,托管此C++里也有接口这一说,也许是一个思路。

我先来试试,再和兄弟你讨论讨论!

#6


思归,还是不行啊,我这次说的详细点:

我那边C++托管的DLL里是这样定义类的(当然外面还有一个空间ClipsWrapper):
public __gc class CClipsWrapper : public iEngine{
...
}
在同一个解决方案里,我又单独建了一个C++托管类库项目,就是iEngine接口的,它.cpp几乎是空的  .h文件里是:

namespace iEngineSpace
{
public __gc __interface iEngine
{
// TODO: 在此添加此类的方法。
};
}
好了,这个解决方案编译OK了.

然后,我在C#项目里用到反射,希望通过iEngine这个接口来实例化一个CClipsWrapper(其实就是希望做一个工厂模式),
在这个C#里,还是象开始我问的那样:

Assembly a = Assembly.LoadFrom(@"D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll");
Type[] Types = a.GetTypes();
//下面省略了循环,因为我ClipsWrapper.dll程序集合里就一个类CClipsWrapper,并且是继承了IEngine这个接口的。
if(t.IsClass && !t.IsAbstract) 
{
//然后我本地项目也引用了这个接口IEngine
//可是运行到下面语句却报错了,说是类型转换出错
iEngine o = (iEngine)Activator.CreateInstance(t);
...
}

其实t类型DEBUG输出已经显示出来就是ClipsWrapper.CClipsWrapper,可就是最后用iEngine一强制转换就报错!

思归,先不要归,帮俺想想办法啊~~~

#7


是啊,我用你给的这个方法
Type[] myObjectArray= t.GetInterfaces();
测试了一下,myObjectArray里好像确实没有什么接口。

而且
object o=Activator.CreateInstance(t);
bool b = o is iEngineSpace.iEngine;
这样测试,b也是“false”,怎么办啊?
那个DLL里的类我确实继承了iEngine啊 

:(

#8


Activator.CreateInstance()返回的是远程对象的代理对象类ObjectHandle,如果要获得远程对象,必须再调用代理对象的Unwrap()方法返回远程对象,将你的代码更改如下:

ObjectHandle hdl = (ObjectHandle)Activator.CreateInstance(t);

IEngine o = (IEngine)hdl.Unwrap();

#9


另:ObjectHandle类是在System.Runtime.Remoting命名空间下

#10


谢谢 timmy3310 了!

可是我照你说的做了,可是在运行到
ObjectHandle hdl = (ObjectHandle)Activator.CreateInstance(t);

还是报“指定转换无效”!

啊~~,我已经精疲力尽了,555555

#11


ObjectHandle hdl;
IEngine    o;
object[]   activationAttributes = {new SynchronizationAttribute()};

hdl = Activator.CreateInstanceFrom(@"D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll", "ClipsWrapper.ClipsWrapper", activationAttributes);
o = (IEngine)hdlSample.Unwrap();

#12


哥们,还是不行啊!!!!

o = (IEngine)hdlSample.Unwrap();
运行到这一步,还是报那个该死的错1

我如果用o = hdlSample.Unwrap();
取出来的就是我要的“ ClipsWrapper.CClipsWrapper”这个类型。

怎么就最后那一步转换过不去呢?呢 呢 呢 ?

#13


...
你的IEngine是在哪个Assembly里定义的啊?
你的第二个工程没有引用第一个工程吧?
那么第二个工程的IEngine哪里来的?

#14


我对Assembly概念不清,但Lostinet说的问题值得关注!

我是这样的:
在一个解决方案里有CClipsWrapper这个类的动态连接库,它实现了接口iEngine.
而接口iEngine定义是在这个解决方案里建的另一个动态连接库项目里单独定义的。
CClipsWrapper类文件是用
include iEngine.h;

using namespace iEngineSpace;
来引入的!

最后,
我用反射方法想通过iEngine接口来实现CClipsWrapper这个实例
这其实是在另一个解决方案里的,这是个纯c#的项目(前面的都是c++托管),
我用
using iEngineSpace;
和用“引入”的方法引入了iEngine.dll这个动态连接库
(当然,我是把上个解决方案里的iEngine.dll拷到这个此c#项目的同一目录下)

就是这样,哪里不对劲啊?

哥们明示!

#15


问题就在你的CClipsWrapper这个工程里。
你应该用:

#using <iEngine.dll>  //这个做法和c#工程是一致的。
来引用你的IEngine接口,而不是include <iEngine.h>
...
否则生成的类并不是iEngine.dll里的interface的实现。

#16


楼上的兄弟,俺照你的指示办事,

有进展,还差一口气!

再来!

我用了下面这段代码测试:

object o = Activator.CreateInstance(t);
bool b = o is iEngineSpace.iEngine;
iEngine eng = (iEngine)o;

布尔变量显示为“true”(以前都是“false”)
可是最后一步:iEngine eng = (iEngine)o;
还是报那个恶心的错误!!!

单步b变量为true时,曾经让俺狂喜一次,可....

#17


兄弟,好像行了,您稍等,容我再试试,

今晚搞定,吐分!

#1


use
Type[] myObjectArray= t.GetInterfaces();

to make sure IEngine is one of them

#2


不要在两个工程同时定义IEngine...

#3


刚才为了说明方便,其实我的D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll是用C++托管写的,而C++托管没有接口这一说,所以我单独做了一个抽象类IEngine(也是C++托管写的DLL),然后ClipsWrapper.dll里的类继承了这个抽象类。

然后象上面那样在C#里强制转换,可是不行,我在DEBUG单步跟的时候,显示o的Basetype确实是IEngine,可就是转不成!

我在想是不是因为我用的是C++托管抽象类的关系呢?

劳驾!

#4


how did you define your C++ interface? like
__gc __interface IMyInterface 

?

#5


不好意思,我不知道托管C++里还有接口这一说,我定义的是一个托管C++的虚函数来代替接口的:
// IEngine.h

using namespace System;

namespace IEngineSpace
{

public __gc class IEngine
{
public:
IEngine(void);
virtual ~IEngine(void);

virtual void reset()=0;

virtual void run()=0;
};
}
现面是CPP文件:
#include "StdAfx.h"
#include "IEngine.h"
#using <mscorlib.dll>

namespace IEngineSpace
{
IEngine::IEngine(void)
{
}

IEngine::~IEngine(void)
{
}

}
我这样写我觉得也没什么问题啊?

不过兄弟你提醒了俺,托管此C++里也有接口这一说,也许是一个思路。

我先来试试,再和兄弟你讨论讨论!

#6


思归,还是不行啊,我这次说的详细点:

我那边C++托管的DLL里是这样定义类的(当然外面还有一个空间ClipsWrapper):
public __gc class CClipsWrapper : public iEngine{
...
}
在同一个解决方案里,我又单独建了一个C++托管类库项目,就是iEngine接口的,它.cpp几乎是空的  .h文件里是:

namespace iEngineSpace
{
public __gc __interface iEngine
{
// TODO: 在此添加此类的方法。
};
}
好了,这个解决方案编译OK了.

然后,我在C#项目里用到反射,希望通过iEngine这个接口来实例化一个CClipsWrapper(其实就是希望做一个工厂模式),
在这个C#里,还是象开始我问的那样:

Assembly a = Assembly.LoadFrom(@"D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll");
Type[] Types = a.GetTypes();
//下面省略了循环,因为我ClipsWrapper.dll程序集合里就一个类CClipsWrapper,并且是继承了IEngine这个接口的。
if(t.IsClass && !t.IsAbstract) 
{
//然后我本地项目也引用了这个接口IEngine
//可是运行到下面语句却报错了,说是类型转换出错
iEngine o = (iEngine)Activator.CreateInstance(t);
...
}

其实t类型DEBUG输出已经显示出来就是ClipsWrapper.CClipsWrapper,可就是最后用iEngine一强制转换就报错!

思归,先不要归,帮俺想想办法啊~~~

#7


是啊,我用你给的这个方法
Type[] myObjectArray= t.GetInterfaces();
测试了一下,myObjectArray里好像确实没有什么接口。

而且
object o=Activator.CreateInstance(t);
bool b = o is iEngineSpace.iEngine;
这样测试,b也是“false”,怎么办啊?
那个DLL里的类我确实继承了iEngine啊 

:(

#8


Activator.CreateInstance()返回的是远程对象的代理对象类ObjectHandle,如果要获得远程对象,必须再调用代理对象的Unwrap()方法返回远程对象,将你的代码更改如下:

ObjectHandle hdl = (ObjectHandle)Activator.CreateInstance(t);

IEngine o = (IEngine)hdl.Unwrap();

#9


另:ObjectHandle类是在System.Runtime.Remoting命名空间下

#10


谢谢 timmy3310 了!

可是我照你说的做了,可是在运行到
ObjectHandle hdl = (ObjectHandle)Activator.CreateInstance(t);

还是报“指定转换无效”!

啊~~,我已经精疲力尽了,555555

#11


ObjectHandle hdl;
IEngine    o;
object[]   activationAttributes = {new SynchronizationAttribute()};

hdl = Activator.CreateInstanceFrom(@"D:\JRs_wrapper\JRsInterface\ClipsWrapper.dll", "ClipsWrapper.ClipsWrapper", activationAttributes);
o = (IEngine)hdlSample.Unwrap();

#12


哥们,还是不行啊!!!!

o = (IEngine)hdlSample.Unwrap();
运行到这一步,还是报那个该死的错1

我如果用o = hdlSample.Unwrap();
取出来的就是我要的“ ClipsWrapper.CClipsWrapper”这个类型。

怎么就最后那一步转换过不去呢?呢 呢 呢 ?

#13


...
你的IEngine是在哪个Assembly里定义的啊?
你的第二个工程没有引用第一个工程吧?
那么第二个工程的IEngine哪里来的?

#14


我对Assembly概念不清,但Lostinet说的问题值得关注!

我是这样的:
在一个解决方案里有CClipsWrapper这个类的动态连接库,它实现了接口iEngine.
而接口iEngine定义是在这个解决方案里建的另一个动态连接库项目里单独定义的。
CClipsWrapper类文件是用
include iEngine.h;

using namespace iEngineSpace;
来引入的!

最后,
我用反射方法想通过iEngine接口来实现CClipsWrapper这个实例
这其实是在另一个解决方案里的,这是个纯c#的项目(前面的都是c++托管),
我用
using iEngineSpace;
和用“引入”的方法引入了iEngine.dll这个动态连接库
(当然,我是把上个解决方案里的iEngine.dll拷到这个此c#项目的同一目录下)

就是这样,哪里不对劲啊?

哥们明示!

#15


问题就在你的CClipsWrapper这个工程里。
你应该用:

#using <iEngine.dll>  //这个做法和c#工程是一致的。
来引用你的IEngine接口,而不是include <iEngine.h>
...
否则生成的类并不是iEngine.dll里的interface的实现。

#16


楼上的兄弟,俺照你的指示办事,

有进展,还差一口气!

再来!

我用了下面这段代码测试:

object o = Activator.CreateInstance(t);
bool b = o is iEngineSpace.iEngine;
iEngine eng = (iEngine)o;

布尔变量显示为“true”(以前都是“false”)
可是最后一步:iEngine eng = (iEngine)o;
还是报那个恶心的错误!!!

单步b变量为true时,曾经让俺狂喜一次,可....

#17


兄弟,好像行了,您稍等,容我再试试,

今晚搞定,吐分!