Archive for October, 2007
Sooner or later you’ll find that you want to make your application extensible. Perhaps you want to add customer specific processing modules to your backend processes. Maybe you’ll want to offer customers the ability to add their own functionality to your base application. VB.NET and the .NET Framework make this relatively easy to do. Let’s walk through the steps.
Define an Interface
The way to load a .NET assembly dynamically is through reflection. To make this process easier and more controllable within the context of an application I’ve found it best to define a plug-in interface, such as this one:
Public Interface IMyPlugIn
Function TestFunction(ByVal value As String) As String
Property MySetting() As String
End Interface
By using the interface this allows us to have a fixed definition for our plug-ins that our main application to work with. This means that we will need less main app code to support our plug-in.
Create A Class
Now we’re ready to create a plug-in class. Here’s the template that gets created:
Public Class CustomerXYZPlugin
Implements MyPlugIn.IMyPlugIn
Public Property MySetting() As String Implements MyPlugIn.IMyPlugIn.MySetting
Get
End Get
Set(ByVal value As String)
End Set
End Property
Public Function TestFunction(ByVal value As String) As String Implements MyPlugIn.IMyPlugIn.TestFunction
End Function
End Class
Now, to complete the plug-in class we will need to add appropriate code it. You can’t define constructors in an interface so you’ll find it best to specify that you’ll either use a parameterless constructor or require that plug-in classes support a specific set of parameters. My preference has been to use parameterless ones and to supply ample properties for the plug-ins.
As for other code, as long as you define the interface you can do just about anything else you want.
Loading The Plug-In
Now we get to the heart of the matter, how to load the plug-in. There are several approaches you can take to this but here’s mine. First, let’s look at the code:
Private Function LoadPlugIn(ByVal LoadPath As String) As MyPlugIn.IMyPlugIn
Dim NewPlugIn As MyPlugIn.IMyPlugIn
Try
Dim PlugInAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom(LoadPath)
Dim Types() As Type
Dim FoundInterface As Type
Types = PlugInAssembly.GetTypes
For Each PlugInType As Type In Types
FoundInterface = PlugInType.GetInterface(“MyPlugIn.IMyPlugIn”)
If FoundInterface IsNot Nothing Then
NewPlugIn = DirectCast(PlugInAssembly.CreateInstance(PlugInType.FullName), MyPlugIn.IMyPlugIn)
Exit For
End If
Next
Catch ex As Exception
‘handle exceptions here
End Try
Return NewPlugIn
End Function
As you can see, we’re passing in the path to our plug-in and returning a plug-in interface object from the call. After declaring our return value we enter a try block. I recommend putting this loader logic in an exception handling block since you may be dealing with code that’s outside your direct control.
Next, we create a new Reflection.Assembly object from the file location that was passed into our function and extract the types from it. This allows a plug-in to have functionality beyond just the interface. We search for our interface and, when we find it, create a new instance and exit our search loop. Then we pass back the newly created plug-in object back to our main code.
Here’s a simple example of what the main code might look like:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim NewPlugIn As MyPlugIn.IMyPlugIn = LoadPlugIn(TextBox1.Text)
NewPlugIn.MySetting = “Hello World”
Dim OurTestPlugInValue As String = NewPlugIn.TestFunction(“Try It!”)
End Sub
Those are the steps to adding a simple plug-in to your application. Of course, there are more things you can do with Reflection and I suggest that you investigate them if you’re thinking about implementing this in one of your apps. Remember that there is a performance penalty for using Reflection and there are security considerations as well so make sure you factor them into your design.
If you have any questions or observations about using Reflection to create plug-ins, let me know by leaving a comment.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
October 9th, 2007
Do you feel like you are in a creative rut either as an individual or a team? How many sacred cows does your organization have? Are they holding you back in developing the best software you can? I started thinking about this after reading the US Navy Monkey Experiment article. Often in software development teams and individual programmers as well, invent sacred cows. These ‘cows’ can be a particular language, tool kit, or methodology. Eventually it gets to the point where the organization, or person, becomes unable and unwilling to adapt to change. Ultimately, it’s a self-defeating paradigm.
I see this a lot in teams and individuals who’re unwilling to move on from VB6. They cling to their sacred cow and refuse to consider alternatives whether it’s VB.NET, C#, Java, or something else. You’ll see this in the fervor some attach to the latest new methodology. The problem is that creative thinking is sacrificed to the cow. People get so locked into the approach they’re using that they’re unable to see the merits of alternative approaches. Like the monkeys in the experiment they attack anyone who tries something out of the norm.
Time for a BBQ?
Is it time that you turn your sacred cows into steaks? Here are some steps you can take.
1. Ask why are we doing things this way?
If you can’t answer this then you might be like the monkeys in the story, simply acting on what someone else told you without really knowing why. But, if you can answer it, then…
2. Ask does this reason still exists?
Maybe you know why you or your team started doing things this way but are the reasons for this still applicable? It may have been a good idea to start a new project in 1998 with VB6 but is it still a good idea in 2007? Perhaps a programming library worked well for Project A but it’s a burden to use it in Project B. Is it really a good idea to use it? Be willing to make some tough choices and stop paying homage to the cow.
3. Ask what are the pluses and minuses of continuing to do things this way?
There could be good reasons to continue doing what you’ve been doing. Are there? Once you’ve reached this point you should prepare yourself to honestly answer if the pluses outweigh the minuses or vice versa. At least by going through the exercise, especially as a team, you should be able to identify where improvement is needed. Sometimes only minor adjustments are needed but other times tougher measures may be required. Sometimes a destructive change, where old ways are discarded, can be helpful. Take the time to evaluate this possibility in yourself or in your team and see if it applies to you.
Let me know if you have made this kind of change or if you think this kind of change isn’t necessary by leaving me a comment. I would like to hear your opinions.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
October 8th, 2007
Here’s another installment of my VB.NET interview questions. Here are the earlier installments:
VB.NET Interview Questions #1.
VB.NET Interview Questions #2.
Feel free to add a comment with your answers. Try to answer them before looking at the comments or searching MSDN or Google for an extra challenge.
True or False
For ‘extra credit’, explain your answer
1. Pop and Push are the primary operations of a Queue data structure.
2. Only certain types of controls have an associated Graphics object.
3. Integers are an example of a reference data type
4. If a class has a MustOverride method in it must also be declared MustInherit.
5. Boxing is the term used to describe the process of sending data to a remote system.
General VB.NET Questions
1. Explain what a SqlDataAdapter is used for.
2. Describe some methods you can use in VB.NET to store binary data.
3. When should you use Regular Expressions?
4. Write an XPath expression that locates all of the ProductDescription nodes in an XML document.
5. Explain the difference between Option Strict and Option Explicit and explain when you should or should not use them.
6. What is the XPathNavigator class and when should you use it?
7. What criteria would you use to determine which string concatenation method to use, i.e. the concatenation operator “&”, String.Concat, or StringBuilder object?
8. How would you convert a Byte array into a String
9. If your database table had date columns that could be null how would you deal with this in your program.
10. If you needed to copy an array of one data type to one of a different data type how would you do it?
Open Ended Questions
1. Your job will be to convert an old VB6 application to a new web based VB.NET/ASP.NET application. Please describe, in general terms, how you would begin this process and what potential risks and problems do you anticipate.
2. A hypothetical company needs a way to send updated pricing in a more timely manner to their resellers. Right now they’re emailing them an Excel file with the changes on a weekly basis. What would you suggest that they do to improve this process?
Have fun with these and let me know what you think about them by leaving a comment or answering the questions.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
October 7th, 2007
Guest Blogging
Aaron of AjaxNinja has asked me to guest blog on his site and, if we work out the logistics, my article should appear over there sometime in the next week or so.
If you would like to guest blog here on VB Notebook for .NET about VB.NET or general software development practices, please send me an email with your proposed idea. I’m always open to doing this.
Most Popular Posts
Here are the 10 most popular posts of the week:
WidgetBucks and BlogRush
WidgetBucks is a brand new advertising program I’m trying out. We’ll see how it goes but it doesn’t look too promising so far. I’ll probably give it another week or two or until someone decides to buy my header banner space.
If you’re the type that scrolls way down the page you may have noticed that I’m giving BlogRush a second chance. A fellow blogger suggested that I try it again since they’ve weeded out a lot of the spam. It still doesn’t give very relevant results or bring much traffic but doesn’t seem spammy or hurting anything so I’ll leave it way down there for now.
Coming Up Next Week
It was suggested that I look more deeply into to coaching team members since last week’s article only scratched the surface so I’ve been researching this topic some this week. Maybe I’ll have an article on this prepared soon. I’m still working on narrowing down some ideas on ADO.NET, XML, and Web Services. I am open to requests, so if there is a topic that you would like for me to cover, let me know in a comment or email.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
October 6th, 2007
You probably know that Generics, introduced to VB.NET in the .NET Framework 2.0, provide type safe Lists, Dictionaries, Stacks, Queues and other objects. But, did you know that you can use the same technique to build your own type safe functions? In this article, we’ll look at some of the basics of doing this.
Why Generics?
First, let’s look at why generics are important.
Prior to generics we had to base any general purpose routines either around a particular type or use System.Object. This meant that we couldn’t make a routine as general purpose as we might want or we had to use performance impacting boxing to place a value type, such as an integer, into a reference type. Plus we had to use type conversions in many places or, worse, not use Option Strict so that we could do implicit conversions.
With generics, we can work with any type but without incurring performance penalties associated with boxing/unboxing variables or doing any casting. More importantly, we’re insuring type safety and thus avoiding troublesome runtime errors. Using them also makes it easier to build single functions that can work with several different data types.
MyFunction(Of T)(…
To begin with, let’s look at how we can define generic type parameters in our own functions. Here’s a simple example that accepts a paramarray of values of a specified type and places then into a generic List of the specified type:
Private Function BuildList(Of T)(ByVal ParamArray values() As T) As List(Of T)
Dim NewList As New List(Of T)
NewList.AddRange(values)
Return NewList
End Function
Notice that when the function is defined we specify a generic type first, (Of T), and then our parameters, followed by our return value. Here are some examples of calling this function:
‘
‘
Dim StringList As List(Of String) = BuildList(Of String)(“test1″, “Hello!”, “Bye!”)
‘
‘
Dim IntList As List(Of Integer) = BuildList(Of Integer)(1, 87, 48, 28, 24)
‘
‘
As you can see we’re calling the same function but using different data types.
You can also specify multiple types and you’re not limited to just using ‘T’ as the name, as we see in this example that merges two lists of the same size into a dictionary object:
Private Function MergeLists(Of TKey, TValue)(ByVal Keys As List(Of TKey), ByVal Values As List(Of TValue)) As Dictionary(Of TKey, TValue)
Dim MergedDictionary As New Dictionary(Of TKey, TValue)
If Keys.Count = Values.Count Then
Dim Counter As Integer
For Each Item As TValue In Values
MergedDictionary.Add(Keys.Item(Counter), Item)
Counter += 1
Next
End If
Return MergedDictionary
End Function
Calling this function would look like these examples:
‘
Dim MyItems As Dictionary(Of Integer, String) = MergeLists(Of Integer, String)(IntList, StringList)
‘
‘
Dim MyInventoryResults As Dictionary(Of Integer, InventoryItem) _
= MergeLists(Of Integer, InventoryItem)(KeyList, MyInventoryItems)
‘
‘
Also, we can have specific types in our paramaters while returning a generic type. For example, this function accepts a DataTable and Integer and returns a List object of the specified type with data from the specified column index.
Public Function ColumnToList(Of T)(ByVal MyTable As DataTable, ByVal columnIndex As Integer) As List(Of T)
Dim ReturnList As New List(Of T)
For Each RowValue As DataRow In MyTable.Rows
ReturnList.Add(DirectCast(RowValue(columnIndex), T))
Next
Return ReturnList
End Function
Any time when you’re coding and you think, “Well, I’ll have to have a separate routine for this data type, and this one, and this one, and this one too”, take the time to consider if using generics will work for you in that case. Often you’ll find that it will.
As always, if you have any questions or ideas on this topic, feel free to leave me a comment.
Share This Article:
These icons link to social bookmarking sites where readers can share and discover new web pages.
October 5th, 2007
Next Posts
Previous Posts