2

これが可能かどうかはわかりません。C#.NETでアセンブリを使用するのはまったく初めてです。

私がやりたいのは、クラスの文字列名が指定されたときにクラスのインスタンスを作成することです。このようなもの:

using MyAssembly;

namespace MyNameSpace
{
     Class MyClass
     {
          int MyValue1;
          int MyValue2;

          public MyClass(string myTypeName)
          {
               foreach(Type type in MyAssembly)
               {
                    if((string)type == myTypeName)
                    {
                         //create a new instance of the type
                    }
               }
               AssignInitialValues(//the type created above)
          }

          //Here I use an abstract type which the type above inherits from
          private void AssignInitialValues(AbstractType myClass)
          {
               this.value1 = myClass.value1;
               this.value2 = myClass.value2;
          }
      }
 }

明らかに、文字列を型と比較することはできませんが、それは私がやろうとしていることを示しています。提供された文字列とは異なるアセンブリで見つかった型を作成します。

何かご意見は?


編集:

試みた後:

var myObject = (AbstractType) Activator.CreateInstance(null, myTypeName);
AssignInitialValues(myObject);

いくつかのエラーが発生します:

  • 一貫性のないアクセシビリティ:パラメータタイプ'MyAssembly.AbstractType'は、メソッド'MyNameSpace.MyClass.AssignInitialValues(MyAssembly.AstractType)'よりもアクセスしにくいです。
  • 'MyAssembly.AstractType'は、保護レベルのためアクセスできません
  • タイプまたは名前空間の名前'MyAssembly'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?)
  • タイプまたは名前空間の名前'AbstractType'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?)

アセンブリが見つからない理由が正確にはわかりません。アセンブリへの参照を追加し、アセンブリの名前空間に使用ディレクティブを使用します。保護レベルに関しては、パブリックにしかできないクラス(またはクラスのコンストラクター)を呼び出しています。

問題がどこにあるかについての手がかりはありますか?


アップデート:

SOに関するいくつかの記事を調べた後、私はこれに出くわしました:https : //stackoverflow.com/a/1632609/360627AbstractTypeクラスを公開することで、一貫性のないアクセシビリティの問題が解決されました。

新しいコンパイラエラーは次のとおりです。

タイプ「System.Runtime.Remoting.ObjectHandle」を「MyAssembly.AbstractType」に変換できません

それが参照する行は次のとおりです。

var myObject = (AbstractType) Activator.CreateInstance(null, myTypeName);

get's meを使用.Unwrap()すると、このエラーを回避できます。これが正しい方法だと思います(不確かです)。ただし、プログラムを実行すると、このコードが呼び出されたときにTypeLoadExceptionが発生します。

TypeLoadException:アセンブリ'MyNameSpace'からタイプ'AbstractType'を読み込めませんでした...

探しているタイプは正しいが、探しているアセンブリが間違っていることがすぐにわかります。メソッドActivator.CreateInstance(String, String)を検索すると、最初の引数としてのnullは、メソッドが実行中のアセンブリを検索することを意味することがわかりました。これは、元の投稿のように必要な動作とは逆です。

MyAssembly最初の引数として使用しようとしましたが、これによりエラーが発生します。

「MyAssembly」は「名前空間」ですが、「変数」のように使用されます

これは弦ではないことが原因だと思います。MyAssemblyただし、試してみる'MyAssembly'と、次のコンパイラエラーが発生します。

  • 文字リテラルの文字が多すぎます
  • 'System.Activator.CreateInstance(System.ActivationContext、string [])'に最適なオーバーロードされたメソッドの一致には、いくつかの無効な引数があります
  • 引数1:「char」から「System.ActivationContext」に変換できません
  • 引数2:「string」から「string[]」に変換できません

間違ったオーバーロードを使おうとしているように私には思えます。

これを修正する方法について何か考えはありますか?

4

3 に答える 3

8

タイプの完全修飾名がある場合は、このforeachループはまったく必要ありません。

var myObject = (SomeBaseType) Activator.CreateInstance(null, myTypeName);
于 2012-09-15T00:16:52.647 に答える
6

あなたのニーズを達成するための多くの方法があります。最高のパフォーマンスではありません:

Activator.CreateInstance(null, myTypeName);

これで作業することもできます:

var ci = Type.GetType(myTypeName).GetConstructor(Type.EmptyTypes);
var myTypeInstance = ci.Invoke(new object[]{})
于 2012-09-15T00:32:41.367 に答える
4

さて、これが答えです。実際のコードを使用してテストしましたが、機能します。それが最善の方法なのか、最も効率的な方法なのかわかりません。他の2つの回答は、正しい方向に進むのに役立ったため、賛成しましたが、ここに完全な回答があります。

using MyAssembly;

namespace MyNameSpace
{
     Class MyClass
     {
          int MyValue1;
          int MyValue2;

          public MyClass(string myTypeName)
          {
               string assemblyName = Assembly.GetAssembly(typeof(AbstractType)).ToString();
               AbstractType selectedClass = (AbstractType)Activator.CreateInstance(assemblyName, myTypeName).Unwrap();
               AssignInitialValues(selectedClass);
          }

          private void AssignInitialValues(AbstractType myClass)
          {
               this.value1 = myClass.value1;
               this.value2 = myClass.value2;
          }
      }
 }

SOとMSDNを検索して、3日間グーグルで検索しましたが、それはあります。アセンブリ名(最初のパラメーター)を使用してクラスをインスタンス化する場合Activator.CreateInstance(String, String)は、.dll(または.exe)の名前だけでなく、完全なアセンブリ名である必要があることに注意してください。

アセンブリ名は、アセンブリに含まれ、定義されていることがわかっているタイプに置き換えることができるstring assemblyName = Assembly.GetAssembly(typeof(AbstractType)).ToString();whereを使用して取得できます。AbstractType

タイプ名(2番目のパラメーター)は、クラス名だけでなく、完全修飾名である必要があります。

于 2012-09-16T05:56:47.270 に答える