Eduardo Molteni
Eduardo Molteni

Reputation: 39413

Best practice for DLL calling an object in the EXE

I'm building a DLL with several "master" objects that need access to the app LINQ DataContext. The DLL will serve several projects with different dataContexts, so I need the DLL can call the object that it's inside the EXE.

What is the best or elegant way to do it?

Edit: Clarification
Code example of what I'm trying to do:

'DLL
'---
Public MustInherit Class MasterObject(Of T As Class)
   Friend db As DataContext
   Public Sub New()
      'How do I do something like this?
      db = New DataContextInTheExe()
   End Sub

   ...

   Public MustOverride Sub Save()
end class

'In the Exe
'---
Public Class Order
   Inherits MasterObject(Of Order)

   Public Overrides Sub Save()
       ...
       Me.db.SubmitChanges()
   End Sub
end class

Upvotes: 1

Views: 518

Answers (3)

eglasius
eglasius

Reputation: 36037

It is still unclear what you want to do, so I will point you to some related answers I have posted:

Regarding structure map, the idea is that you call it like:

var someMaster = StructureMap.GetInstance<SomeMasterDefinedInDll>();

Structure Map will instantiate and pass whatever is needed to the SomeMasterDefinedInDll constructor. You do need to configure it, so you tell it to get the context defined in the exe when a DataContext is requested. Now, usually SomeMasterDefinedInDll is a dependency for something else, so you don't even need to make that code above (it is a parameter of the constructor of something else), you only do that for the top of the hierarchy. Check the links, it is explained pretty clear in there.

Update: In c# syntax, you would:

public abstract class MasterObject<T>
{
    protected MasterObject(DataContext context)
    {
    }
}
public class Order : MasterObject<Order>
{
    public Order() : base(new ExeDataContext()) {}
}

Basically, receive the datacontext as a constructor parameter, and in the subclass pass the datacontext to the base constructor.

Update 2: Note that the above code was in reply to what you wanted to do originally. If you just want to do that, there that will just work (no need for other stuff). That said, I do recommend you look into dependency injection. In that case, the ExeDataContext would be receieved in the Order constructor as well: public Order(ExeDataContext context) : base(context){}

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062770

The most appropriate way to do this is for the exe to pass the data-context to the dll, for example as a method argument to whatever the dll is doing, or as a constructor argument to whatever class (in the dll) needs it. If you have different types of data-contexts, then the type would have to be DataContext or a subclass. Extension methods (on DataContext) are one way of doing this (but not the only way).

Alternatively - in a standard "repository" implementation (where the dll is the repository), it is entirely possible that the caller (the exe) doesn't even know about the data-context - just the ICustomerRepository interface (or whatever) that the dll exposes.


Re the edit; by this alone, it would have no way of knowing the type of data-context to create. You possibly need to either pass a data-context in, or tell it (via generics) the type of data-context; excuse my C#, but:

public abstract class MasterObject<TDataContext, TEntity>
    where TDataContext : DataContext, new()
    where TEntity : class
{
    internal TDataContext db;
    public MasterObject() {
        db = new TDataContext();
    }
}

However, I strongly suspect that the dependency-injection route is simpler - i.e. let the caller tell us:

public abstract class MasterObject<TEntity>
    where TEntity : class
{
    internal DataContext db;
    public MasterObject(DataContext db) {
        this.db = db;
    }
}

Upvotes: 2

Jamie Ide
Jamie Ide

Reputation: 49261

Use dependency injection by passing the data context to the class that needs to consume it in your DLL, typically through its constructor.

Here's an example in C#:

public abstract class MasterObject<T>
{
   private DataContext _dataContext;

   public MasterObject(DataContext dataContext)
   {
      _dataContext = dataContext;
   }
}

public class Order : MasterObject<Order>
{
   public Order(DataContext dataContext) : base(dataContext)
   {
      // additional constructor logic
   }
}

Upvotes: 3

Related Questions