我有一个创建 DLL 的解决方案和另一个使用它们的解决方案。它是一个工具箱,可以将各种工具作为插件加载。起初一切顺利:
这是两个类,都在单独的 cs 文件中:
namespace PIClasses
{
public class PI_base : UserControl
{
public PI_base() { }
public string Description { get; set; }
public string Version { get; set; }
private void InitializeComponent()
{
this.SuspendLayout();
this.Name = "PI_base";
this.ResumeLayout(false);
}
}
}
namespace PIClasses
{
public class PIC_Clock : PI_base
{
private System.ComponentModel.IContainer components = null;
+ protected override void Dispose(bool disposing)
+ private void InitializeComponent()
public System.Windows.Forms.Label st_time;
public System.Windows.Forms.Timer clockTimer;
public PIC_Clock() { InitializeComponent(); }
private void clockTimer_Tick(object sender, EventArgs e)
{ st_time.Text = DateTime.Now.ToString("HH:mm:ss"); }
private void PIC_Clock_Load(object sender, EventArgs e)
{ clockTimer.Enabled = true; }
}
}
这就是工具箱如何在列表框的 selectionchanged 事件中创建一个实例,其中包含找到的 DLL。它被创建得很好,时钟滴答作响..:
string DLLname = lb_tools.SelectedItem.ToString(); // pick one from a list of DLLs
Assembly assembly = Assembly.LoadFrom(DLLname); //load the assembly
foreach (Type type in assembly.GetExportedTypes()) // look for the tool class
{
if (type.Name != "PI_base") // skip the base class
{
var c = Activator.CreateInstance(type);
tp_test2.Controls.Add((Control)c); // I can add is to a tabpage as Control
((Control)c).Dock = DockStyle.Fill; // this works, too
//PI_base ctl = (PI_base)c; // <--this cast gets a runtime error
//PI_base ctl = c; // as PI_base ; // this cast get null
//st_status.Text = ctl.Description; // example of what the base class might deliver
break; // done when we find the real thing
}
但是转换为 PI_base 类会在运行时创建一个无效的转换异常。它说
'“PIClasses.PIC_Clock”类型的对象不能转换为“PIClasses.PI_base”类型。'
好的,但是为什么以及如何正确地做到这一点。我很烦。或者盲人。或者有点笨。或以上任何一种;-)
编辑:
好的,伙计们,这是有道理的——感谢斯科特如此明确地拼写出来。
我接受了您的第二个建议,并为基类创建了一个专用的 PluginCore 项目。
我仍然遇到了一个问题..:我已经将 PluginCore 设为类库 (PI_Base) 并从中生成了一个 DLL (PI_Base.DLL)。
我已经从 ClockPlugin 项目中清除了对原始基类的所有引用,并添加了对 PI_Base.DLL 的引用。我还在 PI_Base 命名空间中添加了 using 子句。我已经从 csproj 目标中删除了原始基类引用。新创建的对基本 DLL 的引用对我来说看起来不错。(?)
但是我在构建时收到“找不到类型或命名空间”错误。这很奇怪,因为我可以右键单击基类类型并说“转到定义”,它会显示它在元数据中找到的东西!但是在构建 ClockPlugin DLL 时,它说既没有找到命名空间 (PI_Base) 也没有找到基本类型 (PI_ToolBase)。
我想我错过了一些小但必不可少的东西..
以下是 csproj 文件的相关部分:
<ItemGroup>
<Reference Include="PI_Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\PI_Base\PI_Base\bin\Debug\PI_Base.dll</HintPath>
</Reference>
<Reference Include="System" />
..
..
<Compile Include="PIC_Clock.cs">
<SubType>UserControl</SubType>
</Compile>
..
..
<Target Name="BuildPlugins">
<CSC Sources="PIC_Clock.cs" TargetType="library"
OutputAssembly="$(OutputPath)PIC_Clock.dll"
EmitDebugInformation="true" />
</Target>
<Target Name="AfterBuild" DependsOnTargets="BuildPlugins">
</Target>
<PropertyGroup>
<PostBuildEvent>call x_copy.bat
</PostBuildEvent>
这是构建失败的 PIC_Clock.cs 部分:
using PI_Base;
namespace PIClasses
{
public class PIC_Clock : PI_ToolBase
编辑 2
事实上,CSC 命令缺少一些重要的东西。它的编译器调用与内部 Studio Build 完全不同,需要告知要包含哪些类以及要引用哪些类。如果我想与另一个程序共享它,我必须引用基类 DLL,例如:
<CSC Sources="PIC_Clock.cs" References="d:\p\c#13\toolbox\pi_base\pi_base\bin\debug\pi_base.dll" TargetType="library" OutputAssembly="$(OutputPath)PIC_Clock.dll" EmitDebugInformation="true" />