|
-
Jan 24th, 2011, 08:25 AM
#1
[RESOLVED] How do instanciate while remaining de-coupled
Just a bit of an issue that we're trying to resolve here. Assuming We're implementing a business model as one dll and a data access layer as another dll. We want them to be de-coupled so we implement an interface for the data-access layer. Great, we could now swap out the data access layer and, as long as the new data access layer fulfils the interface we're good to go, right?
Except we're not. In the business model we need to insanciate the data access layer and, because you can't instanciate an interface, you have to instanciate the actual class. We need to know the name space and the class name.We're going to end up with a line of code somewhere in our business model that looks something like this:-
Dim test as iDataLayer
test = new namespace.DataLayer
Basically, we can declare test as an iDataLayer (the interface) but to instanciate it we need to refer to the actual class (DataLayer). So we haven't really removed the coupling. If we want to swap out the data layer for a different implementation with a possibly different class name or namespace then we need to ammend the code in the business model. We're trying to avoid that.
So far the best we can come up with is to use the activate instance method instead of the New keyword (Late Binding). Because that takes a string we could hold the namespace and classname in a config file or similar, so swapping out one component wouldn't invalidate the others, you'd just need to update the config. That's just our home-spun solution though and I can't help feeling there are betters ways out there.
Can anyone make any suggestion before I start heading up the wrong garden path?
Cheers
Dec
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
-
Jan 24th, 2011, 08:49 AM
#2
Re: How do instanciate while remaining de-coupled
What you're looking for is called Dependency Injection (DI) and/or Inversion Of Control (IoC). Different people will give you slightly different definitions of the two but, generally speaking, IoC is a way of implementing DI. There are lots of IoC containers around that you can use to do what you're after. Basically, the consumer references the IoC container and makes a call to get an object based on an interface. The IoC container has a mapping somewhere (maybe a config file, maybe a mapping file that uses lambdas) that maps interfaces to concrete classes. The code in the consumer might look something like this:
vb.net Code:
Dim something As ISomeInterface = myContainer.GetObject(Of ISomeInterface)()
The consumer is completely decoupled from the producer because the consumer knows only about the interface and the IoC container. To swap in a different producer you simply edit the mappings for the IoC container.
If you search around for those terms you will find plenty of info. There are plenty of choices for IoC containers for .NET, including Unity (Microsoft Enterprise Library), Castle.Windsor and StructureMap.
-
Jan 24th, 2011, 09:00 AM
#3
Re: How do instanciate while remaining de-coupled
That sounds like exactly what we're after. Thanks. That'll give me enough to start googling around and post back the inevitable follow on questions
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
-
Jan 24th, 2011, 09:03 AM
#4
Re: How do instanciate while remaining de-coupled
I know I've not understood your problem fully.
But based on what I got, you have two classes: DataLayer and BusinessLayer. Both implement the IDataLayer interface. And you want to substitute one in place of the other in various implementations.
So what you are doing is correct. You have the class name in string format (how else do you know which class to instantiate at run-time). So Activator.CreateInstance is designed for the same purpose and can be used.
Interfaces are usually used for public exposure and to provide loose coupling with your application. If these are not different projects, then I would recommend using a base class/inherited classes for this. That provides a tight coupling. Here also, you would need to use the Activator.CreateInstance for the same reason - you don't know what class we are instantiating.
-
Jan 24th, 2011, 10:33 AM
#5
Re: How do instanciate while remaining de-coupled
I have a somewhat similar situation. I have an arbitrary number of dlls that provide certain classes all derived from a common base and implementing a certain interface. The key here is that they all implement the certain interface. What I did was loop through all the classes exposed from the dll while examining them with this code:
Code:
ElseIf t.GetInterface("HISInCommon.IRearingUnit") IsNot Nothing Then
Dim o As Object = aDLL.CreateInstance(t.FullName)
What that is doing is that if the class implements the interface I want, then it creates an instance of the object that implements the interface. That object o can then be cast to an instance of the Interface.
However, in this case, what that interface does might also be of interest. In my case, the interface gives me some information about the another type, and it has a method that, when called, creates an instance of that type and returns it. Therefore, the interface has a method that creates an object of a different type.
It seems to me that you could use one of these techniques (and the second one is pretty similar to what JMC was suggesting), to create the object that you need. The first technique would create an instance of your DAL object, then you can cast that to the interface and use it as such.
My usual boring signature: Nothing
 
-
Jan 24th, 2011, 01:37 PM
#6
Re: How do instanciate while remaining de-coupled
Both implement the IDataLayer interface
No. Only the Data Access Layer implements the interface. The business model consumes it. Essentially the interface is describing the contract that the business model requires the data access layer to fulfill.
However, at some point it's likely that we'll want to swap out the data acess layer for a different data access layer. For example, at present we use SQL Server as a backend. If we wanted to use Oracle, or xml or datafiles etc. our current data access isn't going to work because it's sql based. We would need to write a different data access layer that understood the underlying data structure. As long as the new data layer implements the interface we can be assured that the businuess model will continue to function. We've got some requirements of this nature looming so I want to try and crack it now before it becomes a last minute crisis.
What I'm trying to resolve is that, even though the data layer implements the interface, any implementation of it has a different name space and/or class name. When we instanciate it we therefore need to use that namespace and class name in our business model code So if we swapped out the data layer we'd have to rewrite our business model code to use the new namespace and class name. I wanted to break that coupling.
Shaggy, I've got a question about your suggestion. Assuming we end up in a situation where two dlls end up on a machine, both of which implement the interface. I lose control over which gets used don't I? Or is there a way of controlling that. I'm not sure that would ever actually happen but I can't completely rule out the possibility.
I've been playing around a bit with JM's suggestion and so far it looks exactly what I'm after. I'm not convined I really need a third party IOC Container though. Really I just need a config file of some sort (I'll probably stick with an old school ini because then we can manage it by hand and I don't need to provide any configurator screens) and some methods that receieve a request for an object of a given type, create the apropriate object based on the settings and return it. That's actually quite simple and only about an hours coding. Do third party IOC's give me anything else that I should know about before I rule them out though?
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
-
Jan 24th, 2011, 01:57 PM
#7
Re: How do instanciate while remaining de-coupled
Those data layers would be mutually exclusive, isn't it? Only one of them will be used at a time. So why do you need to use a different namespace and/or classname?
-
Jan 24th, 2011, 02:49 PM
#8
Re: How do instanciate while remaining de-coupled
I would say that you do lose control of which gets implemented...sort of. In my case, I look at ALL the dlls in a certain folder and get the items from each interface, so I really don't care which ones are there or how many (a single dll can hold one or more classes that implement the interface). However, I do that because I really don't care which ones I get. In your case, you have a couple options. I am looking at all files in a folder, but you could easily be looking at just one file in a folder, so you could just name the dll a certain way and it would be used. If you want to be able to switch between which dll you used, you could prompt the user to select the one they wanted. You would run into a problem if you had multiple implementations in a single dll, but you can get around that one with a solution that is kind of ugly. Note that I call t.FullName. That is the full name of the type t. In other words, it is the class name. So you do have the means to select based on the type name (full name would include the assembly name), but you shoot yourself in the foot if you put that selection into the code. If you put nice names on the classes, or added a method to the interface that returned a nice name, then you could show those to the user and let them make a selection, or save the one you wanted in a configuration file, but any other means of selecting between them would defeat the whole point of having the interface.
My usual boring signature: Nothing
 
-
Jan 24th, 2011, 05:06 PM
#9
Re: How do instanciate while remaining de-coupled
You are only instantiating the DataLayer implementation once, so it is only that place that is coupled to the implementation. Everywhere else is using the interface, so when you decide to swap it out, you have only a single line of code to change. So from a code change point of view, you're trivially coupled. Given that you'll be deploying a new DataLayer dll anyway, is it the end of the world to deploy a new BusinessLayer dll alongside it?
-
Jan 25th, 2011, 06:39 AM
#10
Re: How do instanciate while remaining de-coupled
So why do you need to use a different namespace and/or classname?
Strictly speaking we don't. We could imlement the subsequent datalayer using the same namespace and classname. However, that feels like an artificial restriction to me and is going to be an annoyance from a code management point of view so I'd rather a better solution.
you have only a single line of code to change
True... but on the flip side we've got a line of code we have to change. That means that whoever's managing the deployment needs to get the business model development team involved etc. It's not a big deal but the fact that you have to open up the business model's black box at all is significant.
Anyway, we've tried the config file and using late binding and it's working perfectly so I'm quite happy with the outcome of this thread. I just want say an extra thanks to everyne who's posted. You're help and thoughts are always welcome.
The best argument against democracy is a five minute conversation with the average voter - Winston Churchill
Hadoop actually sounds more like the way they greet each other in Yorkshire - Inferrd
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|