ですから、現在の状況は、MEFを完全に活用したプログラムを持っているということです。ここで、Rxを利用して、より大きなクエリにスケーリングできるようにし、さまざまなプラグインが結果を返すときにユーザーが結果を確認できるようにします。現在、次のように設定されています。
ワークフロー:クエリ=>決定タイプ=>クエリプラグイン=>結果
現在、私が以下に投稿する以上のものを参照する必要がある場合、コードはすべてGitHubに保存されます。GitHubのALeRT
@Enigmativityの助けを借りて、主要部分は現在Rxで実行されています。それが終わったとき、私はをSystem.IObservable<string>
利用して処理するフレームワークのセットアップがあると思いましたvar.ToObservable()
。これは悲しいことにうまくいかないようです(少なくとも私が持っている限りでは)。プラグインフレームワークは現在、次のように設定されています。
public interface IQueryPlugin
{
string PluginCategory { get; }
string Name { get; }
string Version { get; }
string Author { get; }
System.Collections.Generic.List<string> TypesAccepted { get; }
System.IObservable<string> Result(string input, string type, bool sensitive);
}
私が修正しようとしたが失敗したプラグインのResultメソッドの例は次のようになります。
public System.IObservable<string> Result(string input, string type, bool sensitive)
{
string csv = "\"Roundtrip Time\"," + "\"Status\"\n";
if (sensitive == true)
{
csv += "\"" + "" + "\"," + "\"" + "FORBIDDEN" + "\"\n";
}
else
{
if (type == "URL")
{
input = new Uri(input).Host;
}
Ping ping = new Ping();
PingReply pingReply = ping.Send(input);
csv += "\"" + pingReply.RoundtripTime.ToString() + "\"," + "\"" + pingReply.Status.ToString() + "\"\n";
}
return csv.ToObservable();
}
これにより、当然、次のエラーが発生します。タイプを暗黙的にに変換することはできませんSystem.IObservable<char>
System.IObservable<string>
。
したがって、問題は、プラグインからメインプログラムにデータを渡すための最良の方法は何かということです。状況にメリットがあり、プラグインインターフェイスを比較的シンプルに保つことができれば、タイプの切り替えを処理できます。目標は、独自に作成するすべてのユーザーがプラグインをできるだけシンプルに保つことです。
最後に、MainWindow.xaml.cs全体を下にドロップして、現在すべてがどのように設定されているかを確認します。
using ALeRT.PluginFramework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using GenericParsing;
using System.Windows.Markup;
using System.Data;
using System.Reactive.Linq;
namespace ALeRT.UI
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Directory.GetCurrentDirectory()));
var container = new CompositionContainer(catalog);
try
{
container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
MessageBox.Show(compositionException.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void queryButton_Click(object sender, RoutedEventArgs e)
{
string line;
//resultDS.Reset(); //Looking for a way to clear our the contents from last time without breaking SelectionChanged
if (File.Exists(queryTB.Text) && (bool)listCB.IsChecked)
{
StreamReader file = null;
try
{
file = new StreamReader(queryTB.Text);
while ((line = file.ReadLine()) != null)
{
QueryPlugins(line, DetermineTypes(line), (bool)sensitiveCB.IsChecked);
}
}
finally
{
if (file != null) { file.Close(); }
}
}
else
{
QueryPlugins(queryTB.Text, DetermineTypes(queryTB.Text), (bool)sensitiveCB.IsChecked);
}
}
DataSet resultsDS = new DataSet("Results");
[ImportMany]
public IEnumerable<ITypePlugin> TPlugins { get; set; }
[ImportMany]
public IEnumerable<IQueryPlugin> QPlugins { get; set; }
/// <summary>
/// Method to process all Type plugins.
/// </summary>
private List<string> DetermineTypes(string val)
{
List<string> typeResultAL = new List<string>();
foreach (var tPlugins in this.TPlugins)
{
if (tPlugins.Result(val))
{
typeResultAL.Add(tPlugins.Name);
}
}
return typeResultAL;
}
/// <summary>
/// Method to process all Query plugins.
/// </summary>
private void QueryPlugins(string query, List<string> types, bool sensitive)
{
foreach (string tType in types) //Cycle through a List<string>
{
foreach (var qPlugins in this.QPlugins) //Cycle through all query plugins
{
foreach (string qType in qPlugins.TypesAccepted) //Cycle though a List<string> within the IQueryPlugin interface AcceptedTypes
{
if (qType == tType) //Match the two List<strings>, one is the AcceptedTypes and the other is the one returned from ITypeQuery
{
IObservable<DataTable> q =
from text in qPlugins.Result(query, qType, sensitive)
from tempTable in Observable.Using(
() => new GenericParserAdapter(),
parser => Observable.Using(() => new StringReader(text),
sr => Observable.Start<DataTable>(
() =>
{
var rNum = new Random();
parser.SetDataSource(sr);
parser.ColumnDelimiter = Convert.ToChar(",");
parser.FirstRowHasHeader = true;
parser.MaxBufferSize = 4096;
parser.MaxRows = 500;
parser.TextQualifier = '\"';
var tempTable = parser.GetDataTable();
tempTable.TableName = qPlugins.Name.ToString();
if (!tempTable.Columns.Contains("Query"))
{
DataColumn tColumn = new DataColumn("Query");
tempTable.Columns.Add(tColumn);
tColumn.SetOrdinal(0);
}
foreach (DataRow dr in tempTable.Rows)
dr["Query"] = query;
return tempTable;
}
)))
select tempTable;
}
}
}
}
}
/// <summary>
/// Open a dialog prompt to select a file to process.
/// </summary>
private void browseButton_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "All Files|*.*";
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
queryTB.Text = dlg.FileName;
}
}
private void pluginsLB_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
resultsDG.ItemsSource = resultsDS.Tables[pluginsLB.SelectedValue.ToString()].DefaultView;
}
}
}