DLL を作成するソリューションと、それらを消費する別のソリューションがあります。各種ツールをプラグインとして読み込めるツールボックスです。最初はうまくいきます:
これらは 2 つのクラスで、どちらも個別の 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; }
}
}
これは、ツールボックスが、見つかった DLL を含むリストボックスの selectionchanged イベントでインスタンスを作成する方法です。それはうまく作成され、時計はカチカチ音をたてます..:
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」にキャストできません。
わかりましたが、なぜ、どうすれば正しく行うことができますか。私はイライラしています。またはブラインド。または少しばか。または上記のいずれか;-)
編集:
OK 皆さん、それは理にかなっています - Scott さん、はっきりと説明してくれてありがとう。
私はあなたの 2 番目の提案に行き、基本クラス専用の 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" />