0

私はインターフェースを持っています

public interface ITask
{
  void MethodA();
}

そして、ITaskを実装する2つのクラス

public class TaskA: ITask
{
  public void MethodA();
}

public class TaskB : TaskA,ITask
{
}

ここで、いくつかの条件に基づいて、TaskAまたはTaskBのいずれかのインスタンスを作成したいと思います。ここでジェネリックを使用する方法とオブジェクトを初期化する方法

public void MethodB(int a)
{
  ITask task;
  if(a=1)
  {
    // use TaskA
  }
  else
  {
    //use TaskB
   }
}
4

4 に答える 4

1

ジェネリック型またはメソッド パラメーターがある可能性があることを意味する場合は、次のようにすることができます。

public class A<T> where T : ITask, new()
{
    public void Some() 
    {
         T instanceOfITask = new T();
    }
}

...また:

public class A
{
    public void Some<T>() where T : ITask, new()
    {
         T instanceOfITask = new T();
    }
}

ジェネリック制約を使用すると、T実装するITask必要があり、パラメーターなしのパブリック コンストラクターを持たなければならないことを指定できます。

アップデート

OPが質問を編集したため、私の現在の回答が時代遅れになった可能性があります。

ところで、あなたの実際の要件がわからないので、このソリューションを引き続き使用できると主張できます。

ITaskのインスタンスを処理する必要があるメソッド内でif some 条件を実行する代わりに、呼び出し元で実行し、一般的な制約を再度利用して、リフレクションとそのパフォーマンスの低下を回避できます。

結局のところ、これは抽象ファクトリ パターンを使用しています。

// The abstract factory!
public static class TaskFactory
{
    public static T Create<T>() where T : ITask, new()
    {
         T instanceOfITask = new T();
         // more stuff like initializing default values for the newly-created specific task

         return instanceOfITask;
    }
}

後で、どこか:

ITask task = null;

// Depending on the condition, you invoke the factory method with different implementation of ITask
if([some condition])
{
   task = TaskFactory.Create<MySpecificTaskImplementationA>();
}
else
{
   task = TaskFactory.Create<MySpecificTaskImplementationB>();
}
于 2013-02-12T08:39:48.393 に答える
0

ジェネリックはまったく必要ないようです。ファクトリが必要なようです。以下は単純で単純な実装です。

public static class TaskFactory
{
   public static ITask CreateTask(TaskType taskType)
   {
      switch (taskType)
        cast TaskType.TaskA:
          return new TaskA();
        cast TaskType.TaskB:
          return new TaskB();
        default:
          throw new InvalidArgumentException("unknown task type");
   }
}

ここTaskTypeで、次のように定義された列挙型です。

public enum TaskType
{
   TaskA,
   TaskB,
}

これを次のようなコードで使用できます

ITask myTast = TaskFactory.CreateTask(TaskType.TaskA);

したがって、ご覧のとおり、この場合ジェネリックは必須ではありません。ただし、パラメーターのないコンストラクターがあり、コンパイル時に型がわかっている場合は、ジェネリックを使用して、次のCreateTaskようにメソッドに型パラメーターを提供できます。

public static T CreateTask<T>() where T : ITask, new()
{
   return new T();
}

次のように使用できます。

ITask myTast = TaskFactory.CreateTask<TaksA>();

両方の実装は共存でき、両方が役立つシナリオがあります。

于 2013-02-12T08:43:05.153 に答える
0

あなたのItaskで私たちが持っていると仮定します

public interface Itask
    {
        IQueryable<T> TaskA();
        Iqueryable<T> TaskB();
    }

次に、インスタンスを作成します..

public class Tasks:Itask
    {
        CategoryDataEntities db = new CategoryDataEntities();

        public IQueryable<Category> CategoryList()
        {
            IQueryable<Category> categoryLiist = db.Categories.AsQueryable();

            return categoryLiist;
        }
    }
于 2013-02-12T08:39:15.263 に答える
0

ジェネリックが必要かどうか疑問です。あなたはすでにインターフェイス コントラクトを持っています。これは良いことです。その場合、何らかの入力条件に基づいてインスタンスを構築するファクトリ クラスまたはメソッドが必要です。

Activator.CreateInstance() を使用すると、ITask の実装者が動的に読み込まれるアセンブリに存在する可能性があることが想定されます。

class Factory 
{
    public ITask Build(string input)
    {
        switch(input) {
            case "A":
                return (ITask)Activator.CreateInstance(typeof(TaskA));
            case "B":
                return (ITask)Activator.CreateInstance(typeof(TaskB));
            default;
                throw new Exception();
        }
    }
}
于 2013-02-12T08:40:24.977 に答える