|
分類:[C#]
C#にてとあるアプリケーションを作っていまして、7〜8割できたところです。 環境は、XP Pro、SP2、Visual Studio 2005 Standardです。 最近気づいたのですが(遅すぎ?)、このアプリケーションのexeを取り出して他のプロジェクトに突っ込むと、なんとアプリケーションで使ってたクラスなどpublicで定義した要素が丸見えではないですか。
これはマズいとばかりに、とりあえず、公開したくないものをpublicからinternalへちまちま変更していくことにしました。 ...でも、これはすぐに挫折しました。 1つのpublicをinternalへ変更するたびに、芋づる式に「アクセシビリティ云々」というコンパイルエラーが発生してしまいます。 終りが見えません。
そこでソリューション内部のpublicを一括でinternalへ置換しました。 もちろん、コンパイルエラーがたくさん出ました。 でも、頑張れば何とかなる数(400個程度)でしたし、エラーの種類もほとんど同じものだったので、これでやってみました。 (ちなみにそのエラーとは、internalに置換したことにより、実装されたインターフェースメンバがinternalになってしまったから、などです)
頑張ってコンパイルエラーを全部摘み取り、ビルドできる状態になりました。 ...しかし、今度は実行時エラーが待っていました。 しかも、今までに見たことのない、「MissingMethodException」なる例外です。 ちょっと調べてみると、リフレクション関係ではないですか...。 MSDNによると、「存在しないメソッドに動的にアクセスしようとした場合にスローされる例外。」だそうです。 # いや、動的になんてやってないし。少なくとも自分は。
以上のような状況です。 さて、どこらへんでMissingMethodException例外が投げられるかというと...。 すみません。まんまソースコードは出せるはずがない(長すぎるし、一応商用アプリだし)ので、すごく簡単に説明します。 以下のようなDataGridViewが登場します。
・internal abstract class ProperySettingsGridView : DataGridView { ... } コレクションの全要素のプロパティを編集するためのDataGridView。 内部にobject型の参照をもっており、こいつが編集対象のコレクションを参照している。 コレクションの各要素を行、要素の各プロパティを列にしてセルを編集することで特定の要素の特定のプロパティを編集する。 コレクションを特定したクラスを派生クラスとして利用する。 派生クラスに共通に持たせたい機能(アンドゥなど)も実装。 VirtualModeはtrue。
・internal class RecordsSettingsGridView : ProperySettingsGridView { ... } PropertySettingsGridViewの、コレクションをRecordsクラスに特定したバージョン。
このRecordsSettingsGridViewをフォームRecordsSettingsFormに貼り付けて利用します。 ある情報のまとまり(Records)を編集するためのフォームです。 以下のように、RecordsSettingsFormのコンストラクタでRecordsのインスタンスをRecordsSettingsGridViewに渡しています。 (実際は、コンストラクタから呼ばれるメンバ初期化用の関数Initでやってます。下のスタックトレースからも分かるかと思います)
internal RecordsSettingsForm(Records records) { InitializeComponent(); ... gridView.Records = records; // gridViewはRecordsSettingsGridViewです ... }
ってやってて、さらにRecordsSettingsGridViewのRecordsプロパティの定義は以下です。
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Records Records { get { return (Records)base.Collection; } set { ... if (value == null) base.Collection = null; else base.Collection = value.Clone() as Records; RowCount = Records.Count; // ここでMissingMethodException ... ... } }
コメントとおり、ここで例外が投げられます。 例外のMessageは「このプロジェクトで、引数なしコンストラクタは定義されていません。」です。 StackTraceも書いておきます。 あ、アプリケーションが特定されそうな箇所は伏せています :-)
場所 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) 場所 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) 場所 System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) 場所 System.Activator.CreateInstance(Type type, Boolean nonPublic) 場所 System.Windows.Forms.DataGridViewTextBoxCell.Clone() 場所 System.Windows.Forms.DataGridView.CompleteCellsCollection(DataGridViewRow dataGridViewRow) 場所 System.Windows.Forms.DataGridView.get_RowTemplateClone() 場所 System.Windows.Forms.DataGridViewRowCollection.Add(Int32 count) 場所 System.Windows.Forms.DataGridView.set_RowCount(Int32 value) 場所 --------.RecordsSettingsGridView.set_Records(Records value) 場所 ******** 場所 --------.RecordsSettingsForm.Init(Records records, ******** ********, ++++++++ ++++++++, Boolean @@@@@@@@) 場所 ******** 場所 --------.RecordsSettingsForm..ctor(Records records, ******** ********, ++++++++ ++++++++, Boolean @@@@@@@@) 場所 ******** 場所 --------.RecordsSettingsForm..ctor(Records records, ******** ********, ++++++++ ++++++++) 場所 ******** 場所 --------.RecordsSettingsForm..ctor(Records records, ******** ********) 場所 ******** 場所 --------.========.EditRecords() 場所 ******** 場所 --------.========.btnSettingRecords_Click(Object sender, EventArgs e) 場所 ******** 場所 System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e) 場所 System.Windows.Forms.ToolStripButton.OnClick(EventArgs e) 場所 System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) 場所 System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e) 場所 System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met) 場所 System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met) 場所 System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) 場所 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 場所 System.Windows.Forms.Control.WndProc(Message& m) 場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m) 場所 System.Windows.Forms.ToolStrip.WndProc(Message& m) 場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 場所 System.Windows.Forms.Application.Run(Form mainForm) 場所 --------.Program.Main(String[] args) 場所 ******** 場所 System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args) 場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state) 場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 場所 System.Threading.ThreadHelper.ThreadStart()
「引数なしコンストラクタ」ってのはTraceによるとDataGridViewTextBoxCellのコンストラクタのことでしょうか。 でも、DataGridViewTextBoxCellにはちゃんと引数なしのpublicコンストラクタがあるしなぁ。 もうわけがわかりません。 いったい何が起きているのでしょうか。 internalに置換する前は起きなかったバグなので、置換したことが原因だと思いますが。
以上のことから何か分かる方、なんでも良いですので助言をお待ちしています。 よろしくお願いします。
長くなってすみません。全部読んでくださった方、ありがとうございます:-) あと、詳しいことを書くことができず、申し訳ありません。
|