动态创建对象

时间:2013-02-12 08:35:40

标签: c# interface

我有一个界面

public interface ITask
{
  void MethodA();
}

实现ITask的两个类

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 个答案:

答案 0 :(得分: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 实例的方法中执行如果某些条件,您可以在调用者中再次利用通用约束来避免反射及其性能损失。

在一天结束时,这是使用抽象工厂模式

// 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>();
}

答案 1 :(得分: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;
        }
    }

答案 2 :(得分: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();
        }
    }
}

答案 3 :(得分: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);

因此,正如您所看到的,在这种情况下,泛型不是强制性的。但是,如果你确实有paremeterless构造函数,并且类型在编译时是已知的,那么你确实可以使用泛型为CreateTask方法提供类型参数,如下所示:

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

可以像:

一样使用
ITask myTast = TaskFactory.CreateTask<TaksA>();
这两个实现都可以并存,并且有两种情况都是有用的。