3

私のアセンブリの 1 つには、次の「プロバイダー」タイプが含まれています。

継承ツリー

DeviceInfoProvider基本クラスを使用してプロバイダー情報を保持する XML ファイルもあります。簡略化されたバージョンは次のようになります。

<DeviceInfoProvider Type="SbRioI2CProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>
<DeviceInfoProvider Type="GenericProvider" Assembly="assembly.dll" >
</DeviceInfoProvider>

実行時に、XML フィールドを変数にマップします。

assembly.dll  ⇒ assemblyPath
Type          ⇒ typeName

XML を読み取った後、次のコードを使用して型をインスタンス化します。

var assembly = Assembly.LoadFrom(assemblyPath);

var type = (from t in assembly.GetTypes()
            where t.IsPublic && t.Name == typeName
            select t).FirstOrDefault();

if (type != null)
{
    instance = type.GetConstructor(Type.EmptyTypes).Invoke(null);
}

予想どおり、これによりオブジェクトが適切に生成されます。

インスタンスを基本クラスオブジェクトとしてキャストしようとすると、問題が発生します。

using (var provider = instance as DeviceInfoProvider)
{
    // provider is null!
}

のランタイム型instanceは予想される派生クラスですが、それを基本型に正常にキャストできません。

私は何が欠けていますか?

4

2 に答える 2

2

問題は、LoadFromコンテキストのassembly.dllの型からインスタンス(GenericProvider、SbRioI2CProvider)を作成していることである可能性があります。次に、そのアセンブリ内のタイプ(DeviceInfoProvider)に名前でキャストしようとしています。これは暗黙的にロードコンテキストを使用します。同じアセンブリからのタイプであるが、異なるコンテキストでロードされたタイプは、ランタイムによって異なるタイプと見なされるため、キャストは失敗し、nullになります。この記事では、アセンブリバインディングコンテキストについての追加の説明を提供します。

このキャストを成功させるにAssemblyは、LoadFromコンテキストにロードされているをLoadコンテキストに取得する必要があります。これを行うにはいくつかの方法があります。1つの方法は、アセンブリをGACに配置することです。もう1つは、アセンブリベースからassembly.dllを削除して、プローブで見つからないようにすることです。次に、AppDomain.AssemblyResolveイベントを使用して、AssemblyLoadFromを介して取得したをロードします。

于 2012-04-05T06:20:53.103 に答える
0

反映された型のコンストラクターを呼び出しても、そのインスタンスは作成されません。

反映された型のインスタンスを作成するには、 を呼び出しますActivator.CreateInstance

この行は次のようになります。

if (type != null) {
    instance = Activator.CreateInstance(type)
}

これinstanceにより、タイプobjectが になりますが、必要なものにキャストできるようになりました。

参照: http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

于 2012-04-05T02:22:45.840 に答える