プラグインをサポートする C# でアプリケーションを作成しています。アプリケーションが適切な環境を準備できるように、各プラグインは自己紹介する必要があります。現在の情報オブジェクトは、次のようには見えません。
class FilterInfo
{
public InputInfo[] inputs;
public OutputInfo[] outputs;
bool IsConfigurable;
bool IsPlayable;
string TypeName;
}
この構造は、今後確実に拡大していくでしょう (とはいえ、それほど大きくはないと思いますが、おそらくそのサイズは 2 倍になるでしょう)。私は現在、そのような情報クラスを適切に実装する方法を考えています。
C++ では、次のようにします (例を読みやすくするために、クラスを 1 つのフィールドに取り除きます)。
class FilterInfo
{
private:
std::vector<const InputInfo> inputs;
public:
std::vector<const InputInfo> & GetInputs()
{
return inputs;
}
const std::vector<const InputInfo> & GetInputs() const
{
return inputs;
}
}
現在、プラグインはFilterInfo
クラスをインスタンス化し、そのフィールドに入力してから、要求に応じて戻りconst FilterInfo
、誰も情報の内容を変更できないようにします (そうすべきではありません)。
C# では、次の「安全な」ソリューションしか想像できません。
public interface IInputInfo
{
bool SomeData
{
get;
}
}
public class InputInfo : IInputInfo
{
private bool someData;
public bool SomeData
{
get
{
return someData;
}
set
{
someData = value;
}
}
public bool IInputInfo.SomeData
{
get
{
return someData;
}
}
}
public interface IFilterInfo
{
ReadOnlyCollection<IInputInfo> Inputs
{
get;
}
}
public class FilterInfo : IFilterInfo
{
private InputInfo[] inputs;
public InputInfo[] Inputs
{
get
{
return inputs;
}
set
{
inputs = value;
}
}
public ReadOnlyCollection<IInputInfo> IFilterInfo.Inputs
{
return inputs;
}
}
もちろん、プラグインはIFilterInfo
代わりに を返しFilterInfo
、データが読み取り専用になるようにします (OK、リフレクションについては知っています。問題は、データを変更してはならないことをユーザーに通知することです)。ただし、このソリューションは非常に不器用に見えます。特に、先ほど引用したコンパクト バージョンと比較した場合はなおさらです。
別の解決策として、getter のみを使用して FilterInfo を作成することもできますが、何らかの方法でデータを渡す必要があり、多くのパラメーターを持つ巨大なコンストラクターになる可能性があります。
編集:別の解決策は、構造体を作成し、リクエストごとにそのコピーを返すことです。ただし、配列は参照によってコピーされるため、毎回手動でコピーする必要があります。
さらに別の方法は、誰かが要求するたびに FilterInfo を最初から構築することです。
public FilterInfo Info
{
get
{
return new FilterInfo()
{
IsConfigurable = true,
IsPlayable = false,
Inputs = new[]
{
new InputInfo()
{
// (...)
}
}
}
}
}
この問題を解決するエレガントな方法はありますか?