1

Lets say I want to use, for example, a new DbContext object whenever a method is called in a class but without getting it by a parameter. Like so

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
    }
}

What I was really hoping for was a DI way of doing this. Like public void Method(IMyWayOfContext context).

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

    public virtual void MethodTwo(IMyWayOfContext context) {
    }
}

Other classes inheriting from this class must be provided with a new instance of dbcontext. That's why I don't want to create a new instance inside of the function

Rikard Olsson
  • 841
  • 1
  • 7
  • 28

4 Answers4

1

You could do something like this (generic interface, plus a wrapper with multiple constraints):

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();
    }
}
Baldrick
  • 11,712
  • 2
  • 31
  • 35
0

Make a property with only getter that will return new instance every time

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

EDIT: If you want some kind of dependency injection you can make your class generic and pass to instance of the class what type of context you want

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
    }
}
Simeon Vanov
  • 361
  • 3
  • 13
0

Your simple solution can work this way:

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
    }
}

In that case, you have to take care of disposing InternalContext

Shenron
  • 420
  • 4
  • 11
0

While answer here looks valid, they don't seem to fulfill perfectly your requirement of having a solution that rely on DI.

DI in it's simplest expression is most of the time achieve with Constructor Injection.

Your design was already good and DI ready. Indeed, asking for dependencies via the constructor is good. It is at the composition root of your application that you need to decide what implementation you need to pass.

Using a DI library can help (but it is not required to enable DI).

With your actual class design:

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

Without a factory and with a DI container like SimpleInjector, you could have:

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

And register your component once at the composition root with configurable Lifestyle management:

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

The latter approach is simpler if you want to configure when to inject what instance of your context. Indeed, such configuration is built in an DI Container library. For instance, see: Lifestyle of component with SimpleInjector

plog17
  • 832
  • 8
  • 23
  • Nice! If I'm trying to implement this in a custom library, what is considering being the root? – Rikard Olsson Mar 04 '17 at 12:29
  • A library does not have a composition root. Only application do. Check this article on the subject: http://blog.ploeh.dk/2011/07/28/CompositionRoot/ – plog17 Mar 04 '17 at 13:03
  • Oh ok. Is it common to use DI inside a library? – Rikard Olsson Mar 04 '17 at 13:05
  • In your library you definetly want to have DI in place. Different type of application will have different configuration needed but your librairie should not have to change for that. – plog17 Mar 04 '17 at 13:08
  • Okey, great! Thanx for your answer as well, it made me rethink. I'll probably look into SimpleInjector lib and will try to implement with that – Rikard Olsson Mar 04 '17 at 13:11
  • What kind of application will use you librairy ? – plog17 Mar 04 '17 at 13:12
  • I've got right now three projects. Two of em are .net libs and the third is an asp.net core app. One of the libs has a custom DbContext class that I would like to use in a DI way and that's why the question. Im already using DI between the core app and the second lib, injecting repository classes – Rikard Olsson Mar 04 '17 at 13:41