C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 動的DLLでコレクションクラスのADDのしたデータを取得方法


(過去ログ 138 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■81422 / inTopicNo.1)  動的DLLでコレクションクラスのADDのしたデータを取得方法
  
□投稿者/ yamamoto (3回)-(2016/09/20(Tue) 20:11:55)

分類:[C#] 

開発環境 VS2005
使用言語 C#

 いつも参考にさせて頂いています。

動的に参照するDLLクラスにはコレクションクラスが宣言されています。
動的に参照するDLLと動的に呼び出す画面は別々のプロジェクトです。
動的に呼び出す画面にてコレクションクラスのメンバに対してAddを
行ったデータを表示を行いたいですのですが、記述方法が分かりません。

※動的に呼び出す画面のCの部分が分かりません。

どなたかご教授を願いないでしょうか?

▼動的に参照するDLL
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Othere
{
public class Othere
{
public Othere()
{

}

private string name = string.Empty;

/// <summary>
/// 名前
/// </summary>
public string Name
{
get { return name; }
set { name = value; }
}

private Motimono motimono = new Motimono();

/// <summary>
/// アイテムコレクション
/// </summary>
public Motimono Motimono
{
get { return motimono; }
}

/// <summary>
/// メッセージを表示
/// </summary>
/// <param name="moji"></param>
/// <returns></returns>
public string GetMsg(string moji)
{
string retmoji = string.Empty;

retmoji = name;

return retmoji;

}
}

/// <summary>
/// アイテムコレクションクラス
/// </summary>
public class Motimono : IEnumerable
{
private List<Item> items = new List<Item>();

public void Add(Item item)
{
items.Add(item);
}

public Item this[int index]
{
get { return this.items[index]; }
set { this.items[index] = value; }
}

public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}

/// <summary>
/// アイテムクラス
/// </summary>
public class Item
{
public Item()
{
}

private string itemName = "";

public string ItemName
{
get { return itemName; }
set { itemName = value; }
}
}
}

▼以下 動的に呼び出す画面
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace YobidasiMoto
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
/*
▼参照設定を行った場合
//@
Othere.Othere o = new Othere.Othere();

//A
o.Name = "yamada";

//B
Item i = new Item();
i.ItemName = "pc";
o.Motimono.Add(i);

//C o.Motimono[0].ItemName を取得する方法が不明
MessageBox.Show(o.Name + "持ち物=" + o.Motimono[0].ItemName);
▲参照設定を行った場合
*/

#region @の処理
string dllName = @"C:\app\Othere.dll";
if (!System.IO.File.Exists(dllName))
{
MessageBox.Show("DLL存在エラー");
return ;
}

Assembly asm = Assembly.LoadFrom(dllName);

//Othere型宣言
Type OthereType = asm.GetType("Othere.Othere");

object OthereIns = Activator.CreateInstance(OthereType);
#endregion @の処理

#region Aの処理
PropertyInfo pr_oyaName = null;
pr_oyaName = OthereType.GetProperty("Name");
pr_oyaName.SetValue(OthereIns, "yamamoto", null);
#endregion Aの処理

#region Bの処理
//Item型宣言
Type ItemType = asm.GetType("Othere.Item");
object ItemIns = Activator.CreateInstance(ItemType);

//Itemを格納
PropertyInfo pr_itemName = null;
pr_itemName = ItemType.GetProperty("ItemName");
pr_itemName.SetValue(ItemIns, "pc", null);

//持ち物プロパティ
PropertyInfo pr_mono = null;
pr_mono = OthereType.GetProperty("Motimono");

//Addメソッド
Type MotimonoType = asm.GetType("Othere.Motimono");
MethodInfo mi_mono = MotimonoType.GetMethod("Add", new Type[] { ItemType });

object[] prms = new object[] { ItemIns };
mi_mono.Invoke(OthereIns, prms);

if (pr_mono == null)
{
MessageBox.Show("pr_monoエラー");
}
else
{

}
#endregion Bの処理

#region Cの処理
object GetOyaname = pr_oyaName.GetValue(OthereIns, null);

#region 以下方法が分からない
//o.Motimono[0].ItemName

#endregion 以下方法が分からない

MessageBox.Show((string)GetOyaname);
#endregion Cの処理
}
}
}
引用返信 編集キー/
■81423 / inTopicNo.2)  Re[1]: 動的DLLでコレクションクラスのADDのしたデータを取得方法
□投稿者/ Azulean (713回)-(2016/09/20(Tue) 22:42:57)
続きとしてはこんな感じですかね。
(インデクサは内部的に Item という名前のプロパティになっています)

PropertyInfo itemInfo = MotimonoType.GetProperty("Item");
object item = itemInfo.GetValue(mi_mono, new object[] {0});

Type ItemType = item.GetType();
PropertyInfo itemNameInfo = ItemType.GetProperty("ItemName");
object name = itemNameInfo.GetValue(item);

MessageBox.Show((string)name);
引用返信 編集キー/
■81425 / inTopicNo.3)  Re[2]: 動的DLLでコレクションクラスのADDのしたデータを取得方法
□投稿者/ yamamoto (4回)-(2016/09/21(Wed) 09:18:39)
Azuleanさんご返答ありがとうございます。

解決出来ました。
インデクサは「Item」と言うプロパティなんですね。

今回サンプルプログラムのクラスがItemとなっていますがこのクラス名がItem2変わっても
プロパティはItemなんでよね?
一応プログラムを変更して動作したので大丈夫だとは思いますが。。。

はじめは「this」と言うプロパティを取得しようとしても
nullが返ってくるし途方に暮れていました。

◆変更点
 @2行目 GetValueの第一引数をpr_mono.GetValue(OthereIns, null)に変更
 A5行目 GetValueの第二引数にnullを追加

       1     PropertyInfo itemInfo = MotimonoType.GetProperty("Item");
       2     object item = itemInfo.GetValue(pr_mono.GetValue(OthereIns, null), new object[] { 0 });
       
       3     Type GetItemType = item.GetType();
       4     PropertyInfo itemNameInfo = GetItemType.GetProperty("ItemName");
       5     object name = itemNameInfo.GetValue(item, null);

以上です。

■No81423 (Azulean さん) に返信
> 続きとしてはこんな感じですかね。
> (インデクサは内部的に Item という名前のプロパティになっています)
> 
> PropertyInfo itemInfo = MotimonoType.GetProperty("Item");
> object item = itemInfo.GetValue(mi_mono, new object[] {0});
> 
> Type ItemType = item.GetType();
> PropertyInfo itemNameInfo = ItemType.GetProperty("ItemName");
> object name = itemNameInfo.GetValue(item);
> 
> MessageBox.Show((string)name);

引用返信 編集キー/
■81426 / inTopicNo.4)  Re[3]: 動的DLLでコレクションクラスのADDのしたデータを取得方法
□投稿者/ 魔界の仮面弁士 (903回)-(2016/09/21(Wed) 10:24:31)
2016/09/21(Wed) 11:40:36 編集(投稿者)

No81425 (yamamoto さん) に返信
> インデクサは「Item」と言うプロパティなんですね。

多くの場合はそうなりますが、厳密にいえば
必ずしも "Item" であるとは限らなかったりします。

たとえば、System.String のインデクサ名は "Chars" ですし、
XmlNodeList のインデクサ名は "ItemOf" です。


static void Main()
{
 string strData = "Sample";

 Type t = typeof(String);
 PropertyInfo indexer = t.GetProperty("Chars"); // インデクサ名
 var a = indexer.GetValue(strData, new object[] { 2 });
 var b = ((dynamic)strData).get_Chars(2);
 var c = ((dynamic)strData)[2];
 var d = strData[2];

 Console.WriteLine(a);
 Console.WriteLine(b);
 Console.WriteLine(c);
 Console.WriteLine(d);

 Console.ReadKey();
}



> 今回サンプルプログラムのクラスがItemとなっていますがこのクラス名がItem2変わっても
> プロパティはItemなんでよね?

はい。戻り値の型とは無関係です。
『public Item this[int index]』という現状のコードが
『public Item2 this[int index]』であるとか
『public Item2 this[string key]』になったとしても、
既定のインデクサの名前は "Item" のままです。


その関係で、下記のコードは C#2012 だと "Item" が競合してしまい、
コンパイラ エラー CS0542 が発生します。
C#2015 だと大丈夫なのですけれどね。(2013 は未確認)

// 'Item': メンバー名をそれを囲む型の名前と同じにすることはできません。
public class Item
{
  public string this[int index]
  {
    get { return "[" + index + "]"; }
  }
}

上記を回避するには、C# で IndexerNameAttribute を指定して
インデクサに別の名前を割り当てるようにします。


下記は、"Item" 以外のインデクサを定義する例です。

// C# 実装
public class Item
{
 [System.Runtime.CompilerServices.IndexerName("Languages")]
 public string this[int index]
 {
  get { return new string[] { "VB", "C#", "C++" }[index]; }
 }
}


'VB 実装
Public Class Item
 Default Public ReadOnly Property Languages(ByVal index As Integer) As String
  Get
   Return New String() {"VB", "C#", "C++"}(index)
  End Get
 End Property
End Class


なお、インデクサそのものを取得したいのであれば
Type.GetDefaultMembers を使うことも検討してみてください。
これを使えば、複数のインデクサを持つようなクラスにも対応できます。

ただし、インデクサ以外が DefaultMember として
割り当てられていることもありえますので、
MemberType も合わせてチェックした方が良いでしょう。




> public string GetMsg(string moji)
> {
>   string retmoji = string.Empty;
>   retmoji = name;
>   return retmoji;
> }
これは簡略化すると
 public string GetMsg(string moji) { return this.name; }
というメソッドになりますね。引数 moji が使われていないようです。
引用返信 編集キー/
■81437 / inTopicNo.5)  Re[4]: 動的DLLでコレクションクラスのADDのしたデータを取得方法
□投稿者/ yamamoto (5回)-(2016/09/21(Wed) 17:35:10)
 魔界の仮面弁士さんご返答ありがとうございます。

いつもご回答だけでなく、質問に関連する内容も合わせて
記載して頂き勉強になります。

今後ともよろしくお願いします。

引用返信 編集キー/
■81442 / inTopicNo.6)  Re[5]: 動的DLLでコレクションクラスのADDのしたデータを取得方法
□投稿者/ yamamoto (6回)-(2016/09/23(Fri) 08:49:27)
解決済みにしていませんでした。

ありがとうございました。
今後ともよろしくお願い致します。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -