我有一个类(TabControlH60),这两个从基类(用户控件)继承并实现的接口(IFrameworkClient)。 我实例使用.NET Activator类的对象。 随着返回的情况下,我可以同时投射到用户控件的基类,而不是接口。 我得到的例外是下面的一小段代码片段。 如何转换为界面?
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'."}
我的帽子和我的提供“插件” -Functionality库同样的问题......我终于工作...
这里是我的问题:我有一个主用汇编插件,一个组件,插件(Plugin.dll)AND(重要的)另一个组件提供插件的功能(Library.dll)。
所述Plugin.dll引用的主组件(为了能够延长它),并与插件-FUNC的Library.dll。 - 这是二进制到了一个目录“./Plugins”相对于主要部件。
主要组件还引用的插件,FUNC。 装配,以使用“插件管理”中写道。 这种“插件管理”得到的路径,并通过反射加载所有* .dll文件,以分析是否有“IPlugin” - 接口(其中来自Library.dll太)。
每次我叫插件管理加载它无法施展他们“IPlugin”虽然他们实现它的插件。
我几乎气疯了 - 但后来我发现了问题的全部。 通过编写插件,不仅传出了“Plugin.dll”,但“Library.dll”写入“./Plugins”目录。 意外地加载“Library.dll”我的插件管理,每次我现在有两种类型的“IPlugin”的 - 一个在从主组件和通过插件管理我装一个实际使用的“Library.dll” - 和那些是不兼容的!
注意 - 如果你只是不加载“./Plugins/Library.dll”你仍然遇到问题 - 因为如果你加载‘Plugin.dll’它引用‘Library.dll’,那么它只是使用了在同一个目录下。 .. TILT ...! 我的插件管理现在只是删除“Library.dll”的地方找到它。
线索是:一定不要在不同环境下访问两个组件!
这里最可能的原因是IFrameworkClient
是从不同的组件,在两种情况下,因此是一个不同的.NET类型。 即使是相同的代码,也可以是不同的类型。
检查AssemblyQualifiedName
。 还要注意,如果要加载这个组件,反射,你可以得到不同类型甚至相同AssemblyQualifiedName,由于负载环境。
定义IFrameworkClient接口独立命名空间(必须具有命名空间)独立的项目(类库)。然后添加类库的refrence来控制项目,主体工程
东西告诉我你的示例代码,留下一些东西...
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);
之前剧组。
当Interface
处于不同的组装和我得到我的课动态在run-time
在不同的组件, interface casting
将会失败像你的样品(C#知道我们的界面为不同类型的比一个从继承类)。
这是我在这个情况下,简单而有用的技术:
当我敢肯定,我的Class
已经从提及继承Interface
(EQ。 IFrameworkClient
),所以我写一个魔法行这样的代码 :
dynamic fc = obj as IFrameworkClient ?? (dynamic) obj;
通过这种技术,您可以:
- 这行代码后编写的代码
fc
在design time
对基Interface members
信息和VS编辑智能系统。 - 防止任何接口铸造错误
run-time
笔记:
- 你需要
C# v4
使用dynamic
类型 - 通常我不喜欢用
dynamic
在我的代码类型,但它可以帮助我们在某些情况下,这样的
如果类FPG.H60.AFF.TabControlH60实际上并实现IFrameworkClient应该没有理由,这将失败。 我能想到的唯一的事情导致此例外是如果包含IFrameworkClient大会强烈命名和标签控件对象恰好引用一个不同的版本包含组装,或者您所使用的名称IFrameworkClient不同的接口。
在我来说,我不得不添加一个生成事件复制所需的DLL,因为我是创建实例并分配在运行时的接口类型。 否则,DLL加载可能不是最先进最新的DLL,因此可能无法投射到该接口。
我之所以使用在这种情况下生成事件(而不是添加该DLL作为参考)是该体系结构是这样的:主应用程序应该只引用接口类型,和其他一切应当动态加载。
TLDR; 在从另一个DLL动态加载类型的情况下,确保您复制最近该DLL使用生成事件的bin目录的版本,否则铸造时看来,它应该可能无法正常工作。
演员是行不通的,因为你试图从类型转换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