1

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" />
4

1 に答える 1