tags:

views:

153

answers:

3

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
+2  A: 

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;
    }
}
Marc Gravell
How would you do it using extension methods?
Eduardo Molteni
Do you mean having the extension method in the exe? how would the DLL know about the extension?
Eduardo Molteni
No, the extension method would be in the dll. An extension method is just a fancy way of passing an instance into a utility (shared/static) method.
Marc Gravell
Well, that's not what I'm trying to do. I have added a code example, hope it helps.
Eduardo Molteni
That's it, thanks!
Eduardo Molteni
+2  A: 

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
   }
}
Jamie Ide
Could you give me an example?
Eduardo Molteni
No idea why this was down-voted (fix); I agree entirely.
Marc Gravell
Although the answer is completely right, I have choosed Marc's answer because it's more complete. Thanks!
Eduardo Molteni
+1  A: 

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

eglasius
I added an example code, hope it is more clear what I'm trying to do
Eduardo Molteni
@Eduardo updated with how to - added the syntax in c# though, with a comment to clear it up ...
eglasius
@Freddy: Your sample code doesn't use dependency injection because the dependency is still created in the dll and not injected from the exe.
Jamie Ide
@Jaime you are absolutely correct, that code was in reply to Eduardo's update on what he was trying to do.
eglasius