在类的每个方法中提供一个新的对象实例?

时间:2017-03-03 10:27:45

标签: c# dependency-injection inversion-of-control dbcontext

让我们说,只要在类中调用方法但是没有通过参数获取它,我想使用新的DbContext对象。像这样

class MyClass {
    public virtual void MethodOne() {
        // Having automatically a new instance of DbContext
    }

    public virtual void MethodTwo() {
        // Also having automatically a new instance of DbContext
    }
}

我真正希望的是这样做的DI方式。与public void Method(IMyWayOfContext context)一样。

class MyClass {
    public virtual void MethodOne(IMyWayOfContext context)) {
    }

    public virtual void MethodTwo(IMyWayOfContext context) {
    }
}

必须为从此类继承的其他类提供dbcontext的新实例。这就是为什么我不想在函数

中创建新实例的原因

4 个答案:

答案 0 :(得分:1)

您可以执行类似的操作(通用接口,以及具有多个约束的包装器):

class DBContext{ }

interface IDoesMethods<TContext> where TContext : new()
{
    void MethodOne(TContext context = default(TContext));
    void MethodTwo(TContext context = default(TContext));
}


class MyClass : IDoesMethods<DBContext>
{
    public void MethodOne(DBContext context)
    {            
    }

    public void MethodTwo(DBContext context)
    {            
    }
}

class MyContextWrapper<TClass, TContext> : IDoesMethods<TContext> where TContext : new() where TClass : IDoesMethods<TContext>, new()
{
    public void MethodOne(TContext context = default(TContext))
    {
        instance.MethodOne(new TContext());        
    }

    public void MethodTwo(TContext context = default(TContext))
    {
        instance.MethodTwo(new TContext());
    }

    private TClass instance = new TClass();
}

class Program
{
    static void Main(string[] args)
    {
        var wrapper = new MyContextWrapper<MyClass, DBContext>();
        wrapper.MethodOne();
        wrapper.MethodTwo();
    }
}

答案 1 :(得分:0)

创建一个只有getter的属性,每次都会返回新实例

   protected DbContext MyDBContext 
   {
       get 
       { 
         return new DbContext(); 
       }
   }

编辑:如果你想要某种依赖注入,你可以让你的类通用,并传递给类的实例你想要什么类型的上下文

class MyClass<T> {

    protected DbContext MyDBContext 
    {
       get 
       { 
          return Activator.CreateInstance<T>();
       }
    }

    public void MethodOne() {
        // Having automatically a new instance of DbContext
    }

    public void MethodTwo() {
        // Also having automatically a new instance of DbContext
    }
}

答案 2 :(得分:0)

您的简单解决方案可以这样工作:

class MyClass {
    protected DbContext InternalContext {
        return new DbContext();
    }

    public virtual void MethodOne(DbContext dc = null) {
        if(dc == null)
            dc = InternalContext;
        // do your work
    }

    public virtual void MethodTwo(DbContext dc = nnull) {
        if(dc == null)
            dc = InternalContext;
        // do your work
    }
}

在这种情况下,您必须处理处理InternalContext

答案 3 :(得分:0)

虽然这里的答案看起来有效,但它们似乎并不完全符合您对依赖DI的解决方案的要求。

DI中最简单的表达方式是大多数情况下使用构造函数注入实现。

您的设计已经很好并且已准备就绪。 实际上,通过构造函数请求依赖是很好的。 在应用程序的组合根目录中,您需要确定需要传递的实现。

使用DI库可以提供帮助(但不需要启用DI)。

根据您的实际课程设计:

class MyClass {
   public virtual void MethodOne(IMyWayOfContextFactory contextFactory)) {
      using(var context = contextFactory.Create()){
          //play with context
      }
   }
   public virtual void MethodTwo(IMyWayOfContextFactory contextFactory) {
      using(var context = contextFactory.Create()){
          //play with context
      }
   }
}

public ContextFactory : IMyWayOfContextFactory {
     IMyWayOfContext Create(){
        return new MyWayOfContext();
     }
}

没有工厂和像SimpleInjector这样的DI容器,你可以拥有:

class MyClass {
   public virtual void MethodOne(IMyWayOfContext context)) {
          //play with context
   }
   public virtual void MethodTwo(IMyWayOfContext context) {
          //play with context       
   }
}

使用可配置的生活方式管理在组合根目录注册您的组件一次:

container.Register<IMyWayOfContext, MyWayOfContext>(Lifestyle.Transient);

如果要配置何时注入上下文的实例,后一种方法会更简单。实际上,这种配置是在DI Container库中构建的。例如,请参阅:Lifestyle of component with SimpleInjector