17

一連の型で使用するためのラッパー ジェネリック クラスがあります。これらの型はユーティリティによって生成され、すべて基本クラス ClientBase から派生します。ClientBase にはデフォルトのコンストラクターしかありませんが、生成されたすべての型にはデフォルトのコンストラクターがあり、コンストラクターはパラメーターとして文字列を取ります。ラッパー クラスのコンストラクターでは、文字列を受け取るコンストラクターを使用して型のインスタンスをインスタンス化します。サンプルコードは次のとおりです。

public class ClientBase
{ }

public class GenericProxy<T>
    where T: ClientBase, new()
{
    T _proxy;

    public GenericProxy(string configName)
    {
        _proxy = new T(configName);    
    }
}

型 T は文字列を受け取るコンストラクターを持つことが保証されていないため、このコードはコンパイルされません。ジェネリック クラスに制約を定義して、型 T に文字列を受け取るコンストラクターが必要であることを強制する方法はありますか? これが不可能な場合、この種の状況を処理するための適切な代替手段は何ですか?

4

5 に答える 5

24

不可能です。これを処理する「静的インターフェース」を見たいのですが、すぐには期待できません...

代替案:

  • T のファクトリとして機能するデリゲートを指定する
  • T のファクトリとして機能する別のインターフェイスを指定する
  • T初期化のために T 自体にインターフェイスを指定します (インターフェイスを実装するように制約を追加します)。

最初の 2 つは実際には同等です。基本的に、プロキシ クラスを次のように変更します。

public class GenericProxy<T>
    where T: ClientBase, new()
{
    string _configName;
    T _proxy;
    Func<string, T> _factory;

    public GenericProxy(Func<string, T> factory, string configName)
    {
        _configName = configName;
        _factory = factory;
        RefreshProxy();
    }

    void RefreshProxy() // As an example; suppose we need to do this later too
    {
        _proxy = _factory(_configName);
    }
}

(後でさらにインスタンスを作成する必要があると思います。それ以外の場合は、コンストラクターに T のインスタンスを渡すこともできます。)

于 2009-05-12T16:40:00.273 に答える
4

残念ながら、あなたがやろうとしていることは不可能です。

型制約に関する MSDN の記事

于 2009-05-12T16:39:41.707 に答える
2

これはメソッドを制約する実際の質問には答えませんが、完全を期すために、リフレクションを使用して実行時に求めていることを実行する方法を次に示します。

private T  Get<T>(string id)
    {
    var  constructor = typeof(T).GetConstructor(new Type[] { typeof(X), typeof(Y) });
    if (constructor == null)  throw new InvalidOperationException("The type submitted, " + typeof(T).Name + ", does not support the expected constructor (X, Y).");

    var  data = GetData(id);
    return (T)constructor.Invoke(new object[] { data.x, data.y });
    }
于 2014-07-21T23:47:16.157 に答える
1

Jonが指摘しているように、これには組み込みのサポートはありませんが、Expression. これを行うコードは、MiscUtil (内MiscUtil.Linq.Extensions.TypeExt) にあります。

于 2009-05-12T19:15:37.727 に答える