.NET:无法将对象转换为它实现的接口
我有一个类(TabControlH60),它既继承自基类(UserControl)又实现了一个接口(IFrameworkClient)。我使用 .NET Activator 类实例化该对象。使用返回的实例,我可以转换为 UserControl 基类,但不能转换为接口。我得到的异常位于代码片段下方。如何投射到界面?
object obj = Activator.CreateInstance(objType);
Type[] interfaces = obj.GetType().GetInterfaces(); // contains IFrameworkClient
m_Client = (UserControl)obj; // base class cast works
IFrameworkClient fc = (IFrameworkClient)obj; // interface cast fails
// Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window.
{"Unable to cast object of type 'FPG.H60.AFF.TabControlH60' to type
'FPG.AFF.Interfaces.IFrameworkClient'."}
I have a class (TabControlH60) that both inherits from a base class (UserControl) and implements an interface (IFrameworkClient). I instantiate the object using the .NET Activator class. With the returned instance, I can cast to the UserControl base class, but not to the interface. The exception I get is below the code snipet. How do I cast to the interface?
object obj = Activator.CreateInstance(objType);
Type[] interfaces = obj.GetType().GetInterfaces(); // contains IFrameworkClient
m_Client = (UserControl)obj; // base class cast works
IFrameworkClient fc = (IFrameworkClient)obj; // interface cast fails
// Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window.
{"Unable to cast object of type 'FPG.H60.AFF.TabControlH60' to type
'FPG.AFF.Interfaces.IFrameworkClient'."}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我的一个提供“插件”功能的库也有同样的问题...我终于让它工作了...
这是我的问题:我有一个使用插件的主程序集,一个带有插件的程序集(Plugin.dll)并且(重要)提供插件功能的另一个程序集 (Library.dll)。
Plugin.dll 引用了主程序集(以便能够扩展它)和带有插件函数的 Library.dll。 - 它的二进制文件位于相对于主程序集的目录“./Plugins”。
主程序集还引用了插件函数。程序集是为了使用“PluginManager”而编写的。这个“PluginManager”获取路径并通过反射加载所有 *.dll 文件,以便分析是否存在“IPlugin”接口(也来自 Library.dll)。
每次我调用 PluginManager 加载插件时,它都无法将它们转换为“IPlugin”,尽管它们实现了它。
我几乎要生气了——但后来我发现了整个问题。通过编译插件,不仅将“Plugin.dll”写入“./Plugins”目录,而且还将“Library.dll”写入“./Plugins”目录。通过每次使用我的 PluginManager 意外加载“Library.dll”,我现在有两种类型的“IPlugin” - 一种在主程序集中使用的实际“Library.dll”中,另一种是通过我的 PluginManager 加载的 - 并且这些是不兼容的!
注意 - 如果您不加载“./Plugins/Library.dll”,您仍然会遇到问题 - 因为如果您加载引用“Library.dll”的“Plugin.dll”,那么它只会使用同一目录中的那个。 ..倾斜...!!我的 PluginManager 现在只是删除它找到的“Library.dll”。
线索是:确保不要在不同的上下文中访问两个程序集!
I hat the same problems with a library of mine providing "plugin"-functionality... I got it finally working...
Here was my problem: I had one main assembly using plugins, one assembly with the plugin (Plugin.dll) AND (important) another assembly providing the plugin-functionality (Library.dll).
The Plugin.dll referenced the main assembly (in order to be able to extend it) and the Library.dll with the plugin-func. - it's binaries got to a directory "./Plugins" relative to the main assembly.
The main assembly also referenced the plugin-func. assembly in order to use the "PluginManager" is wrote. This "PluginManager" gets a path and loads all *.dll files via reflection in order to analyze if there is a "IPlugin"-interface (which comes from Library.dll too).
Everytime I called the PluginManager to load the plugins it could not cast them to "IPlugin" although they implemented it.
I nearly got mad - but then I found out the whole problem. By compiling the plugin there was not only the "Plugin.dll" but the "Library.dll" written to the "./Plugins" directory. By accidentally loading the "Library.dll" every time with my PluginManager I now had two types of "IPlugin" - one in the actual "Library.dll" that is used from the main assembly and one that was loaded through my PluginManager - and those were incompatible!
Attention - if you just do not load "./Plugins/Library.dll" you nevertheless encounter the problem - because if you load "Plugin.dll" which references "Library.dll" then it just uses the one in the same directory... TILT...!! My PluginManager now just deletes "Library.dll" where it find it.
The clue is: Be sure that you do not access two assemblies in different contexts!
最可能的原因是,在这两种情况下,
IFrameworkClient
来自不同的程序集,因此是不同的 .NET 类型。即使是相同的代码,也可以是不同的类型。检查
AssemblyQualifiedName
。另请注意,如果您使用反射加载此程序集,即使具有相同的 AssemblyQualifiedName,您也可以获得不同的类型,这要归功于加载上下文。The most likely cause here is that
IFrameworkClient
is from a different assembly in the two cases, and is thus a different .NET type. Even if it is the same code, it can be a different type.Check the
AssemblyQualifiedName
. Note also that if you are loading this assembly with reflection you can get a different type even with the same AssemblyQualifiedName, thanks to the load-context.在独立工程(类库)的独立命名空间(必须有命名空间)中定义IFrameworkClient接口,然后将类库的引用添加到Control工程和主工程中
Define IFrameworkClient Interface in independent namespace (must be have namespace) of independent project (class library).Then add refrence of the class library to Control project and main project
当
接口
在不同的程序集中并且我在运行时
在不同的程序集中动态获取我的类时,接口转换
将像您的示例一样失败(C# 知道我们的接口是与从该接口继承的类不同的类型)。在这种情况下,这是我简单而有用的技术:
当我确定我的
Class
已从上述Interface
继承时code> (eq.IFrameworkClient
),所以我写了一行神奇的代码,如下所示:通过这种技术,您可以:
fc
代码在设计时
基于接口成员
信息和vs编辑器智能系统。运行时
出现任何接口转换错误注释:
C# v4
才能使用动态
类型dynamic
类型,但在某些情况下它可以帮助我们,比如这样When the
Interface
is in a different assembly and i get my class dynamically atrun-time
in a different assembly,interface casting
will be failed like your sample (C# knows our interface as a different type than which one the class inherited from that).This is my simple and useful technique in this cases:
When I'm sure my
Class
has inherited from the mentionedInterface
(eq.IFrameworkClient
), so i write one magic line of code like this:By this technique you can:
fc
atdesign time
base onInterface members
info and vs editor intelligences system.run-time
Notes:
C# v4
to usedynamic
typedynamic
types in my codes but it can help us in some cases like this有些东西告诉我你的示例代码遗漏了一些东西......
这可以编译并运行。
我敢打赌,在您尝试强制转换之前,包含 IFrameworkClient 定义的 DLL 尚未加载。当您使用 Activator.CreateInstance 时可能会发生这种情况。
尝试在转换之前插入
var forceLoad = typeof(IFrameworkClient);
。Something tells me your sample code is leaving some stuff out...
This compiles and runs.
I'm betting that the DLL containing the definition of IFrameworkClient hasn't yet been loaded before you try to cast. This can happen when you're using Activator.CreateInstance.
Try inserting
var forceLoad = typeof(IFrameworkClient);
before the cast.如果类 FPG.H60.AFF.TabControlH60 实际上确实实现了 IFrameworkClient,则没有理由会失败。我能想到的导致此异常的唯一原因是,如果包含 IFrameworkClient 的程序集被强命名,并且选项卡控件对象恰好引用了包含程序集的不同版本,或者您正在使用名为 IFrameworkClient 的不同接口。
If the class FPG.H60.AFF.TabControlH60 actually does implement IFrameworkClient there should be no reason this would fail. The only thing I can think of that causes this exception is if the assembly that contains IFrameworkClient is strongly named and the Tab Control object happens to reference a different version of the containing assembly or your are using a different interface with the name IFrameworkClient.
就我而言,我必须添加一个构建事件来复制所需的 DLL,因为我是在运行时创建实例并分配给接口类型。否则,加载的 DLL 可能不是最新的 DLL,因此可能无法转换为接口。
在这种情况下,我使用构建事件(而不是添加 DLL 作为引用)的原因是,该体系结构使得主应用程序应该只引用接口类型,而其他所有内容都应该动态加载。
太长了;
在从另一个 DLL 动态加载类型的情况下,请确保使用构建事件将该 DLL 的最新版本复制到 bin 目录,否则在看起来应该工作时,转换可能无法工作。
In my case I had to add a build event to copy the needed DLL since I was creating instances and assigning to interface types at run time. Otherwise the DLL loaded might not be the most up-to-date DLL, and therefore may not cast to the interface.
The reason I used build events in this case (instead of adding the DLL as a reference) is that the architecture is such that the main application should only reference the interface types, and everything else should be loaded dynamically.
TLDR;
In the case of loading types dynamically from another DLL, make sure you copy the most recent version of that DLL to the bin directory using build events, otherwise casting may not work when it appears that it should.
我遇到了同样的问题,我只是添加了以下代码
虽然,在生产中它永远不会成为问题,但在单元测试中它是问题,但现在我不需要再次加载它并创建“不同类型”
I ran into same issue and I just added the following code
Although, in production it will never be a problem, in unit test it was but now I don't need to load it again and create a "different type"
转换不起作用,因为您正在尝试从类型
object
转换为接口。如果将接口转换行替换为:IFrameworkClient fc = (IFrameworkClient)m_Client;
它将起作用。
或者,我稍微确定您可以使用
as
运算符将对象转换为接口。请参阅这篇文章了解更多信息:
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference- Between-as-and-cast-operators.aspx
的另一部分谜。接口不是从
对象
派生的:http://blogs. msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx
The cast isn't working because you're trying to cast from type
object
to the interface. If you replace the interface cast line with:IFrameworkClient fc = (IFrameworkClient)m_Client;
It will work.
Alternately, I'm mildly certain that you could do the cast from the object to the interface with the
as
operator.See this article for more information:
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
One more piece of the puzzle. Interfaces do not derive from
object
:http://blogs.msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx