- PR -

Type.GetType アセンブリはロードされていない?

投稿者投稿内容
未記入
会議室デビュー日: 2004/08/31
投稿数: 12
投稿日時: 2007-02-21 13:54
長文ですみません。VB初心者です。VB2005 ExpressEditionを利用しています。

クラス名からインスタンスを生成する処理を実装するために、
.NET TIPS「すでにアセンブリがロードされている場合」(Type.GetTypeの利用)
を参考にしたのですが、思った動作がされません。
http://www.atmarkit.co.jp/fdotnet/dotnettips/386createinstance/createinstance.html

前提:
 上記サイトのサンプルをそのままコピーして実行した際、
 Type.GetType("MasterClass")ではエラーとなり、
 Type.GetType("[プロジェクト名].MasterClass")としなくてはいけませんでした。
 タイプが取得できていないようでした。なにか設定が必要なのでしょうか?

本題:
 クラス名からインスタンスを生成する処理を共通化(dllで実装)するように変更してみました。
 下記のように実装し、プロジェクト2はプロジェクト1を参照しています。

 JediMasterChildを実行した際、 Activator.CreateInstance(masterType)の個所で、
  System.ArgumentNullException: 値を Null にすることはできません。
  パラメータ名: type
 という例外が発生します。タイプが取得できていないようです。

 GetTypeを実行するのは、JediMasterChildで、
 同じプロジェクト内にインスタンス化したいクラス(PadawanClass)が存在するので、
 「アセンブリはロードされている」状態と考えたのですが、違うのでしょうか?


補:
 生成したいクラス(MasterClass,PadawanClass)だけ別のdllにし、
 JediMasterParentで、Assembly.GetTypeを利用すれば、
 JediMasterChildでインスタンスを取得できることは確認しています。

コード:

プロジェクト1:InstanceSampleDll(クラスライブラリ)
Public MustInherit Class JediClass
Public MustOverride Sub Say()
End Class

Public MustInherit Class JediMasterParent
Public Function Create(ByVal className As String) As JediClass
'タイプ取得
Dim masterType As Type = Type.GetType(className)
'インスタンス生成
Dim instance As Object = Activator.CreateInstance(masterType)
'キャスト
Dim Jedi As JediClass = CType(instance, JediClass)
Return Jedi
End Function
End Class


プロジェクト2:InstanceSample(アプリケーション)

Public Class JediMasterChild Inherits InstanceSampleDll.JediMasterParent
Shared Sub Main()
Dim test As JediMasterChild = New JediMasterChild()
'クラス名指定
Dim padawan = test.Create("InstanceSample.PadawanClass")
padawan.say()
End Sub
End Class

Public Class MasterClass Inherits InstanceSampleDll.JediClass
Public Overrides Sub Say()
Console.WriteLine("Use the Force")
End Sub
End Class
Public Class PadawanClass Inherits InstanceSampleDll.JediClass
Public Overrides Sub Say()
Console.WriteLine("Yes, Master")
End Sub
End Class



[ メッセージ編集済み 編集者: 未記入 編集日時 2007-02-21 15:19 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-21 14:28
引用:

未記入さんの書き込み (2007-02-21 13:54) より:

前提:
 上記サイトのサンプルをそのままコピーして実行した際、
 Type.GetType("MasterClass")ではエラーとなり、
 Type.GetType("[プロジェクト名].MasterClass")としなくてはいけませんでした。
 タイプが取得できていないようでした。なにか設定が必要なのでしょうか?


いいえ、"プロジェクト名" ではなく '名前空間' を含めて、「完全修飾名」 にする必要があります。

引用:

本題:
 クラス名からインスタンスを生成する処理を共通化(dllで実装)するように変更してみました。
 下記のように実装し、プロジェクト2はプロジェクト1を参照しています。

 JediMasterChildを実行した際、 Activator.CreateInstance(masterType)の個所で、
  System.ArgumentNullException: 値を Null にすることはできません。
  パラメータ名: type

 という例外が発生します。タイプが取得できていないようです。


まあ、必然とそうなるでしょうね。
前提で躓いているわけですから。

<null> < 何もないおいらに何をしろというのだ!!

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
未記入
会議室デビュー日: 2004/08/31
投稿数: 12
投稿日時: 2007-02-21 14:51
> じゃんぬねっと さん

引用:

いいえ、"プロジェクト名" ではなく '名前空間' を含めて、「完全修飾名」 にする必要があります。


プロジェクトのプロパティでルートの名前空間を空欄にすることで、
Type.GetType("MasterClass") で実行できました。
デフォルトで、'名前空間'に'プロジェクト名'が設定されているのですね。
ありがとうございました。

引用:

まあ、必然とそうなるでしょうね。
前提で躓いているわけですから。



質問の内容が不明瞭ですみません。疑問点は下記の方です。
引用:

 GetTypeを実行するのは、JediMasterChildで、
 同じプロジェクト内にインスタンス化したいクラス(PadawanClass)が存在するので、
 「アセンブリはロードされている」状態と考えたのですが、違うのでしょうか?


なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2007-02-21 15:09
引用:

未記入さんの書き込み (2007-02-21 13:54) より:

クラス名からインスタンスを生成する処理を実装するために、
.NET TIPS「アセンブリがロードされていない場合」(Type.GetTypeの利用)
を参考にしたのですが、思った動作がされません。
http://www.atmarkit.co.jp/fdotnet/dotnettips/386createinstance/createinstance.html


この記事は参考にしないことをおすすめします。
通常のアプリでLoadFromを使うべきではないし、
アセンブリがその時点でロード済みかどうかは通常は意識するべきではないし、
ロード済みだという判断だけで、アセンブリを指定しないType.GetTypeを使用しても正しく動作しません。

Type.GetTypeにアセンブリ名を含む型名を指定するか、
もしくはAssenbly.Loadでアセンブリ名を指定してアセンブリへの参照を取得し、
そのGetTypeを呼び出します。
※すでにアセンブリがロード済みかどうかには関係なくどちらでも問題ありません。

LoadFromはどちらかというと特殊な用途で使うもので、基本はLoadです。
未記入
会議室デビュー日: 2004/08/31
投稿数: 12
投稿日時: 2007-02-21 15:18
すみません。質問文に誤りがありました。
誤:.NET TIPS「アセンブリがロードされていない場合」(Type.GetTypeの利用)
正:.NET TIPS「すでにアセンブリがロードされている場合」(Type.GetTypeの利用)
質問文を修正します。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-21 15:25
引用:

未記入さんの書き込み (2007-02-21 14:51) より:

GetTypeを実行するのは、JediMasterChildで、
同じプロジェクト内にインスタンス化したいクラス(PadawanClass)が存在するので、
「アセンブリはロードされている」状態と考えたのですが、違うのでしょうか?


これ、質問の中に答えがありませんか。
"同じプロジェクト内" にあるということは '同じアセンブリ' ですよ。

おうむ返しみたいになってしまって申し訳ありません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
未記入
会議室デビュー日: 2004/08/31
投稿数: 12
投稿日時: 2007-02-21 16:04
何度もありがとうございます。

引用:

じゃんぬねっとさんの書き込み (2007-02-21 15:25) より:

"同じプロジェクト内" にあるということは '同じアセンブリ' ですよ。




GetTypeを利用しているメソッドCreateはJediMasterParentに実装し、
JediMasterParentと生成されるインスタンスのインタフェースJediClassは プロジェクト1に存在します。
JediMasterParentを継承して、Createを呼んでいるJediMasterChildと、
生成されるインスタンス(JediClassを継承)、MasterClass,PadawanClassは プロジェクト2に存在します。
プロジェクト1をDLLにし、プロジェクト2から参照しています。
JediMasterChildを実行します。

JediMasterChildは、MasterClass,PadawanClassと同プロジェクトなので、アセンブリがロードされている状態、
JediMasterParentは、MasterClass,PadawanClassと別プロジェクトなので、アセンブリがロードされていない状態、
ということになりますが、
JediMasterParentにMasterClass,PadawanClassをロードしなくてはいけないのでしょうか?
実行するJediMasterChildにロードされていればよいだろうと考え、上のソースになりました。

#考え方が正しいとしたら、なぜ動かないのか。。。
未記入
会議室デビュー日: 2004/08/31
投稿数: 12
投稿日時: 2007-02-21 16:10
引用:

なちゃさんの書き込み (2007-02-21 15:09) より:

この記事は参考にしないことをおすすめします。
通常のアプリでLoadFromを使うべきではないし、
アセンブリがその時点でロード済みかどうかは通常は意識するべきではないし、
ロード済みだという判断だけで、アセンブリを指定しないType.GetTypeを使用しても正しく動作しません。



LoadとLoadFormの違いについては、もう少し勉強します。
私の目的では、Assembly.GetTypeを利用するなら、
なちゃさんのおっしゃる通りLoadでよいようです。
ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)