外部モジュールの動的ロードをサポートするアプリケーションを開発しようとしています。C#(。NET v4.5)を使用して外部アセンブリをロードすることからいくつかの記事を読み、以下のコードを取得しました。ただし、それは機能しておらず、外部モジュールでサブクラスを検出していません。
外部アセンブリをロードするためのコードは次のとおりです。
byte[] array = <HERE I LOAD THE DLL>
Assembly asb = Assembly.Load(array);
Type[] types = GetAssemblyTypes(asb);
for( int i = 0; i < types.Length; i++ )
{
Type t = types[i];
if( t != null && typeof(App).IsAssignableFrom(t) /*t.IsSubclassOf(typeof(App))*/ )
{
app.AppClass = (App)Activator.CreateInstance(t);
return true;
}
}
これがGetAssemblyTypes()です
private Type[] GetAssemblyTypes(Assembly asb)
{
Type[] types;
try
{
types = asb.GetTypes();
}
catch( ReflectionTypeLoadException ex )
{
types = ex.Types;
}
return types;
}
これがメインアプリケーションのクラスです(このクラスはモジュールによって使用されます)
namespace MyApplication.API
{
public class App
{
// CODE
}
}
これが私のモジュールの例です:using MyApplication.API;
namespace HelloWorld
{
class HelloWorld : App
{
}
}
重要なポイントは次のとおりです。1-モジュールのクラス名がわかりません。Appクラスのサブクラスになることはわかっています。
問題は、types.Lengthは1を与えますが、types [i]でアクセスしようとすると、nullポインターを与えることです。ここで何かが足りませんか?
@CadBurryコードに基づいた半動作バージョンを入手しました。
byte[] bytes = <HERE I LOAD THE DLL>
Assembly asb = Assembly.Load(bytes);
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve;
IEnumerable<Type> types = asb.GetExportedTypes().Where(w => w.IsSubclassOf(typeof(App)));
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= CurrentDomain_ReflectionOnlyAssemblyResolve;
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
if(types.Count() > 0)
{
Type type = types.FirstOrDefault();
if( type == null )
return false;
app.AppClass = (App)Activator.CreateInstance(type);
return true;
}
メソッドを使用して:
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if( args.Name.Contains(typeof(MyApplication).Assembly.GetName().Name) )
{
return Assembly.GetExecutingAssembly();
}
return null;
}
private Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly asb = AppDomain.CurrentDomain.GetAssemblies().Where(w => w.FullName == args.Name).FirstOrDefault();
return asb;
}
上記のコードを使用すると、メインアプリケーションの現在のディレクトリ(プラグインフォルダなど)にない場合でも、アセンブリを読み込むことができます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加