5

ジェネリックの依存性注入ハンドラー(ベースのサービスロケーター)で作業しているときに、ジェネリックの問題が発生しています。

編集1(わかりやすくするため)

さて、私は実際にSimpleInjectorをDIリゾルバーとして使用しており、GetInstanceメソッドにクラス制約があるため、より完全なコードを次に示します。

  public T GetInstance<T>() where T : class
  {
     try
     {
        // works
        return _container.GetInstance<T>();
     }
     catch( ActivationException aEx )
     {
        return default( T );
     }
  }

  public T GetInstance<T>()
  {
     try
     {
        if( typeof( T ).IsClass )
        {
           // does not work, T is not a reference type
           return _container.GetInstance<T>();
        }
     }
     catch( ActivationException aEx )
     {
        return default( T );
     }
  }

編集2-コメントでは奇妙に見えるので、最終的なコード:

  public T GetInstance<T>()
  {
     try
     {
        if( typeof( T ).IsClass )
        {
           return (T) _container.GetInstance(typeof(T));
        }
     }
     catch( ActivationException aEx )
     {
        return default( T );
     }
  }
4

3 に答える 3

1

簡単に言うと、少なくとも直接では、これを行うことはできません。コンパイラは、Tが常にクラスになることを完全に保証するために多くの作業を行う必要があるため、GetEvenMoreGenericInstanceに同じ型制約を適用せずに、Tを汎用型パラメータとして渡すことはできません。

これは、リフレクションを介して実現することも、Typeをパラメーターとして受け取るGetInstanceの非ジェネリックオーバーロードを作成することもできます。Typeパラメーターオプションをお勧めするか、このメソッドを呼び出す必要がないようにコードを完全に再構築することをお勧めします。

于 2012-08-23T13:26:05.007 に答える
1

もう1つのヘルパーメソッドを使用できますか?以下のテストクラスを見つけてください

public class Test
{
  public T GetInstance<T>() where T : class
  {
    return (T)GetInstance(typeof(T));
  }

  private object GetInstance(Type type) 
  {
     return Activator.CreateInstance(type);
  }

  public T GetEvenMoreGenericInstance<T>()
  {
     if( !typeof( T ).IsValueType )
     {
        return (T)GetInstance(typeof(T));
     }
     return default( T );
  }
}
于 2012-08-23T13:26:16.703 に答える
0

リフレクションを使用してのバリアントを見つけてからGetInstance、適切なものを呼び出すことができます。

次の例では静的メソッドを呼び出しますが、拡張することもできます。

namespace Scratch
{
    internal class Foo
    {
      // A class to create
    }

    class Program
    {
        public static T GetInstance<T>() where T : class, new()
        {
            return new T(); // Or whatever...
        }

        public static T CallGeneric<T>(Func<object> f)
        {
            var method = f.Method;

            var converted = method.GetGenericMethodDefinition().MakeGenericMethod(typeof(T));

            return (T) converted.Invoke(null, new object[] {});
        }

        public static T GetEvenMoreGenericInstance<T>()
        {
            if(!typeof(T).IsValueType)
            {
                return CallGeneric<T>(GetInstance<object>);
            }
            return default(T);
        }

        static void Main( string[] args )
        {
            var a = GetEvenMoreGenericInstance<int>();
            var b = GetEvenMoreGenericInstance<Foo>();
        }
    }
}
于 2012-08-23T13:38:19.627 に答える