プラグイン フレームワークを作成し、C# でリフレクションによって依存関係を読み込もうとしています。私の現在の実装は次のとおりです。
public interface IPlugin : IDisposable
{
void Run();
}
public interface IPluginProxy : IDisposable
{
void RunProxy();
void LoadDependencies(string pluginDirectoryPath, AppDomain pluginDomain);
}
public class PluginProxy : MarshalByRefObject, IPluginProxy, IDisposable
{
private List<IPlugin> pluginTypes = null;
public void ProcessProxy()
{
//loop thorough plugin types and call Run on all plugins
foreach(var pluginType in pluginTypes)
{
pluginType.Run();
}
}
public void LoadDependencies(string pluginDirectoryPath, AppDomain pluginDomain)
{
pluginTypes = Utility.LoadAssembliesAndGetPluginTypes(pluginDirectoryPath, pluginDomain);
}
//TODO:
public void Dispose(){}
}
public Class Utility
{
public static List<IPlugin> LoadAssembliesAndGetPluginTypes(string pluginDirectoryPath, AppDomain pluginDomain)
{
try
{
var pluginTypes = new List<IPlugin>();
var pluginsDirectory = new DirectoryInfo(pluginDirectoryPath);
var files = pluginsDirectory.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
foreach (FileInfo file in files)
{
// Load the assembly into the child application domain.
Assembly assembly = pluginDomain.Load(AssemblyName.GetAssemblyName(file.FullName));
var iPluginTypes = zGetTypes(assembly);
pluginTypes.AddRange(iPluginTypes.ToList());
}
return pluginTypes;
}
catch (Exception ex)
{
throw ex;
}
}
private static IEnumerable<IPlugin> zGetTypes(Assembly assembly)
{
var myPlugins = from y in assembly.GetTypes()
where y.IsClass && y.GetInterface("IPlugin") != null &&
y.GetConstructor(Type.EmptyTypes) != null
select Activator.CreateInstance(y) as IPlugin;
return myPlugins;
}
}
新しいアプリケーション ドメインを作成する Windows サービスがあります。次に、PluginProxy を取得し、LoadDependencies と ProcessProxy を呼び出します。依存関係を子ドメインにロードしようとしていることに注意してください。
問題は zGetTypes メソッドにあります。このメソッドは、IPlugin の種類を見つけることができます (intellisense が示しています)。ただし、Activator.CreateInstance を呼び出しても、型は初期化されません (null)。
子ドメインにいる場合、zGetTypes はタイプ IPlugin のインスタンスを作成できないことに注意してください。
アセンブリ アセンブリ = pluginDomain.Load(AssemblyName.GetAssemblyName(file.FullName));
別のアプリドメインを作成せず、アセンブリをメインのアプリドメインにロードするだけで、インスタンスの作成が機能します。私の場合、サービスの appdomain は子 appdomain を作成します。プラグインのアセンブリをプロキシにロードする責任をプッシュしたい。Proxy は MarshalByRefObject から派生するため、インスタンスを作成して Windows サービス側からアンラップできます。
その後、サービスはプラグインの読み込みとライフサイクル管理をプロキシに委任します。プロキシは、LoadDependencies へのメソッド パラメーターを介して子 appdomain のコンテキストを取得します。
IPlugin のインスタンスが作成されない理由はありますか?