我有一个类(TabControlH60),它继承自基类(UserControl)并实现一个接口(IFrameworkClient)。我使用.NET Activator类实例化对象。使用返回的实例,我可以转换为UserControl基类,但不能转换为接口。我得到的例外是在代码snipet下面。我如何投射到界面?
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'."}
答案 0 :(得分:37)
我遇到了同样的问题,我的图书馆提供了“插件”功能......我终于让它工作了......
这是我的问题:我有一个使用插件的主程序集,一个带插件的程序集(Plugin.dll)和(重要)另一个程序集提供插件功能(Library.dll)。
Plugin.dll引用了主程序集(为了能够扩展它)和带有plugin-func的Library.dll。 - 它的二进制文件到达了相对于主程序集的目录“./Plugins”。
主程序集也引用了plugin-func。汇编为了使用“PluginManager”写的。这个“PluginManager”获取一个路径并通过反射加载所有* .dll文件,以分析是否存在“IPlugin”接口(也来自Library.dll)。
每当我调用PluginManager加载插件时,虽然他们实现了插件,但它无法将它们转换为“IPlugin”。
我差点生气 - 但后来我发现了整个问题。通过编译插件,不仅有“Plugin.dll”而且“Library.dll”写入“./Plugins”目录。每次使用我的PluginManager意外加载“Library.dll”时,我现在有两种类型的“IPlugin” - 一个在主程序集中使用的实际“Library.dll”中,另一个是通过我的PluginManager加载的 - 那些是不相容的!
注意 - 如果你只是不加载“./Plugins/Library.dll”,你仍会遇到问题 - 因为如果你加载“Plugin.dll”引用“Library.dll”那么它只是使用了同一个目录... TILT ...... !!我的PluginManager现在只删除它找到它的“Library.dll”。
线索是:确保您不会在不同的上下文中访问两个程序集!
答案 1 :(得分:11)
这里最可能的原因是IFrameworkClient
来自两种情况下的不同程序集,因此是不同的.NET类型。即使它是相同的代码,它也可以是不同的类型。
检查AssemblyQualifiedName
。另请注意,如果使用反射加载此程序集,则可以使用相同的AssemblyQualifiedName 获得不同的类型,这要归功于load-context。
答案 2 :(得分:4)
在独立项目(类库)的独立命名空间(必须具有命名空间)中定义IFrameworkClient接口。然后将类库的引用添加到Control项目和主项目
答案 3 :(得分:3)
有些东西告诉我你的示例代码会遗漏一些东西......
class Program
{
static void Main(string[] args)
{
var type = typeof(MyClass);
object obj = Activator.CreateInstance(type);
Type[] interfaces = obj.GetType().GetInterfaces();
var m_Client = (UserControl)obj;
IFrameworkClient fc = (IFrameworkClient)obj;
}
}
public interface IFrameworkClient { }
public class UserControl { }
public class MyClass : UserControl, IFrameworkClient { }
编译并运行。
我打赌在尝试投射之前尚未加载包含IFrameworkClient定义的DLL。当您使用Activator.CreateInstance时会发生这种情况。
尝试在演员表之前插入var forceLoad = typeof(IFrameworkClient);
。
答案 4 :(得分:2)
如果Interface
在另一个程序集中 ,并且我在run-time
的另一个程序集中动态动态,{{1}将像你的样本一样失败(C#知道我们的接口与另一个类继承的类型不同)。
在这种情况下,这是我简单实用的技巧:
当我确定我的interface casting
继承了上面提到的Class
(例如Interface
)时,我写了一行魔法代码这样:
IFrameworkClient
通过这种技术,你可以:
dynamic fc = obj as IFrameworkClient ?? (dynamic) obj;
信息和编辑智能系统fc
,在design time
代码的这一行代码后面编写代码。Interface members
备注:强>
run-time
才能使用C# v4
类型dynamic
类型,但在某些情况下它可以帮助我们答案 5 :(得分:0)
如果类 FPG.H60.AFF.TabControlH60 实际上确实实现了IFrameworkClient,那么就没有理由这会失败。我唯一能想到的是导致此异常的原因是,包含IFrameworkClient的程序集是强命名的,并且Tab Control对象恰好引用了包含程序集的不同版本,或者您正在使用名为IFrameworkClient的其他接口。
答案 6 :(得分:0)
在我的情况下,我必须添加一个构建事件来复制所需的DLL,因为我在运行时创建实例并分配给接口类型。否则,加载的DLL可能不是最新的DLL,因此可能无法转换为接口。
我在这种情况下使用构建事件(而不是添加DLL作为参考)的原因是该体系结构使得主应用程序应该只引用接口类型,其他所有内容都应该动态加载。
TLDR; 在从另一个DLL动态加载类型的情况下,请确保使用构建事件将该DLL的最新版本复制到bin目录,否则当它看起来应该时,强制转换可能不起作用。
答案 7 :(得分:0)
我遇到了同样的问题,我只是添加了以下代码
library(dplyr)
df %>%
group_by(ID) %>%
mutate(count_n = dense_rank(Date))
# ID Date need count_n
# <fct> <date> <dbl> <int>
#1 x1 2006-08-23 1 1
#2 x1 2006-08-30 2 2
#3 x1 2006-08-30 2 2
#4 X2 2006-09-06 1 1
#5 X3 2006-09-13 1 1
#6 x1 2006-09-20 3 3
尽管在生产中这将永远不是问题,但在单元测试中却是,但是现在我不需要再次加载它并创建“不同类型”
答案 8 :(得分:-1)
由于您尝试从类型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
又一块拼图。接口不是从object
派生的:
http://blogs.msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx