Writing Application "Drivers"

J

Jonathan Wood

Greetings,

I'm a long-time C++ developer, currently writing a C# Windows Forms
application.

I have a case where an application needs some functionality that varies
depending on the current data. I know I could easily write different methods
or even classes and then call the appropriate one, but I'm thinking more in
terms of "plug ins" that can be written and called from my app.

In C++, I might use DLLs for this. I could use LoadLibrary to load the
appropriate "driver", the name of which could be a string that is part of my
data.

Any suggestions on a cool approach with C#? I really don't have a good feel
for how modules are located or loaded with .NET.

Thanks.

Jonathan
 
J

Jesse Houwing

* Jonathan Wood wrote, On 28-12-2009 17:44:
Greetings,

I'm a long-time C++ developer, currently writing a C# Windows Forms
application.

I have a case where an application needs some functionality that varies
depending on the current data. I know I could easily write different
methods or even classes and then call the appropriate one, but I'm
thinking more in terms of "plug ins" that can be written and called from
my app.

In C++, I might use DLLs for this. I could use LoadLibrary to load the
appropriate "driver", the name of which could be a string that is part
of my data.

Any suggestions on a cool approach with C#? I really don't have a good
feel for how modules are located or loaded with .NET.

Thanks.

Jonathan

Jonathan,

Have a look at the new 3.5 AddIn Framework:
http://www.shafqatahmed.com/2008/01/new-net-35-fe-1.html
 
J

Jonathan Wood

Mark Rae said:

I must confess, I don't get this.

Putting the really stupid sites aside, the basic idea seems to be code like
this:

public interface ITest
{
public void Method() { }
}

public class Test1 : ITest
{
public void Method() { }
}

public class Test2 : ITest
{
public void Method() { }
}

public class TestFactory
{
public ITest GetTest1() { return new Test1; }
public ITest GetTest2() { return new Test2; }
}

I'm not sure how this helps. Specifically:

1. How is calling TestFactory.GetTest1() any better than calling new
Test1()?

2. How is an interface better, or even as good as using inheritance? At
least, with inheritance, the base class could contain methods that are
reused in the derived class.

I'm just having trouble seeing any advantage to this code.

BTW, what does seem like it would be useful is if I could add a class type
to a table somehow. For example, let's say the class type is keyed off a
string. I could create an array of those strings along with corresponding
class types. But what kind of data could I store that my code could create
an appropriate object from. I realize I could use if/else or even switch,
but that could be improved on.

Thanks.

Jonathan
 
J

Jonathan Wood

Jonathan Wood said:
BTW, what does seem like it would be useful is if I could add a class type
to a table somehow. For example, let's say the class type is keyed off a
string. I could create an array of those strings along with corresponding
class types. But what kind of data could I store that my code could create
an appropriate object from. I realize I could use if/else or even switch,
but that could be improved on.

Hmm... Perhaps Activator.CreateInstance(typeof(i)) is the answer.

Jonathan
 
A

Arne Vajhøj

I have a case where an application needs some functionality that varies
depending on the current data. I know I could easily write different
methods or even classes and then call the appropriate one, but I'm
thinking more in terms of "plug ins" that can be written and called from
my app.

In C++, I might use DLLs for this. I could use LoadLibrary to load the
appropriate "driver", the name of which could be a string that is part
of my data.

Any suggestions on a cool approach with C#? I really don't have a good
feel for how modules are located or loaded with .NET.

More or less the same way.

You put the driver in a DLL and you load that.

The call is just Assembly.Load instead of LibraryLoad.

Note that .NET DLL's and Win32 DLL's are not quite the same,
but for this purpose it is the same.

Arne
 
A

Arne Vajhøj

1. How is calling TestFactory.GetTest1() any better than calling new
Test1()?

It is better if the factory uses strings to to load.
2. How is an interface better, or even as good as using inheritance? At
least, with inheritance, the base class could contain methods that are
reused in the derived class.

Implementing interfaces is more popular in OO than inheriting
implementation today.

But that discussion is not directly related to your problem.

Arne
 
A

Arne Vajhøj

Hmm... Perhaps Activator.CreateInstance(typeof(i)) is the answer.

I will suggest:

IFoobar o = (IFoobar)Assembly.Load(dllnam).CreateInstance(clznam);

where the class do implement IFoobar.

Arne
 
P

Peter Duniho

Jonathan said:
Thanks, this looks interesting. On closer inspection, I'm not sure it
makes good sense for my current task, but I could definitely see putting
this to use sometime.

Do you need dynamic, run-time loading of the code? If so, then I think
the Add-In Framework is in fact a very good bet.

If not, then your "driver" is no more than any other DLL you might add
as a static reference to your project and use the code from in an
explicit way. Using the factory pattern may or may not be desirable,
but that decision would not be affected by the whether or not you need
to dynamically load the code. You can use the factory pattern either way.

Pete
 
J

Jonathan Wood

Peter Duniho said:
Do you need dynamic, run-time loading of the code? If so, then I think
the Add-In Framework is in fact a very good bet.

If not, then your "driver" is no more than any other DLL you might add as
a static reference to your project and use the code from in an explicit
way. Using the factory pattern may or may not be desirable, but that
decision would not be affected by the whether or not you need to
dynamically load the code. You can use the factory pattern either way.

I'm still trying to decide how I want to implement this. After considering
it for a while, I'm not sure there is any advantage to dynamically loading
the driver, although I am glad to have information on how to implement that
(as I mentioned).

After thinking about it, what I really need to be able to do for my current
task is dynamically create an object of a type indicated by data in my
database.

Thanks.

Jonathan
 
J

Jonathan Wood

Arne Vajhøj said:
It is better if the factory uses strings to to load.

Do you have an example of this? I think I know what you mean and kind of
have something working like this. But I'm not sure I know what you mean.
Implementing interfaces is more popular in OO than inheriting
implementation today.

But that discussion is not directly related to your problem.

I have a pretty good feel for OOP. I was just trying to figure out if this
suggested approach had benefits. As I see it, an interface is better when I
don't know where the object will come from. But inheritance makes better
sense if I can place all my classes in the same code.

Thanks.

Jonathan
 
J

Jonathan Wood

Arne Vajhøj said:
IFoobar o = (IFoobar)Assembly.Load(dllnam).CreateInstance(clznam);

where the class do implement IFoobar.

This syntax is pretty interesting. I'll have to explore this further.

Thanks.

Jonathan
 
P

Peter Duniho

Jonathan said:
I'm still trying to decide how I want to implement this. After
considering it for a while, I'm not sure there is any advantage to
dynamically loading the driver, although I am glad to have information
on how to implement that (as I mentioned).

I think that information has been provided, both in terms of the way one
used to have to do it (Assembly.Load(), etc.) and in terms of what .NET
supports today (Add-In Framework).
After thinking about it, what I really need to be able to do for my
current task is dynamically create an object of a type indicated by data
in my database.

The most general-purpose solution would in fact still use reflection,
where you use the Activator.CreateInstance() overload that takes as an
argument the names of the assembly and type you want to create (the
assembly name can be null if you just want the current assembly to be
used to find the type).

However, note that reflection is very slow and prone to maintenance
problems due to the extra code complexity. If you can avoid the wholly
general-purpose solution, that would be better. For example, create
your own string-based factory. It could be as simple as something like
this:

void CreateInstance(string strType)
{
switch (strType)
{
case "ClassA":
return new ClassA();
case "ClassB":
return new ClassB();
// etc.
}
}

It may get somewhat more complicated if you need to pass arguments to
the constructors, but not really more complicated than using Activator.

The downside is that you can only deserialize from the database types
that your code specifically knows about. But, hopefully the only types
that wind up in the database in the first place are those that your code
specifically knows about.

Pete
 
A

Arne Vajhøj

Do you have an example of this? I think I know what you mean and kind of
have something working like this. But I'm not sure I know what you mean.

If the factory takes both assembly name and class name as arguments.
I have a pretty good feel for OOP. I was just trying to figure out if
this suggested approach had benefits.

It has.
As I see it, an interface is
better when I don't know where the object will come from.

It is often better due to less coupling.
But
inheritance makes better sense if I can place all my classes in the same
code.

I don't think the organization of the source code should drive the
OO design.

Arne
 
J

Jonathan Wood

Arne Vajhøj said:
It is often better due to less coupling.


I don't think the organization of the source code should drive the
OO design.

As I see it, inheritance provides a number of advantages over interfaces.
However, when you don't know where the object is coming from, the decoupling
you mentioned may outweigh those advantages.

Jonathan
 
J

Jonathan Wood

Peter Duniho said:
However, note that reflection is very slow and prone to maintenance
problems due to the extra code complexity. If you can avoid the wholly
general-purpose solution, that would be better. For example, create your
own string-based factory. It could be as simple as something like this:

Yeah, the code below is what I'm playing with so far. If I could avoid the
lookup, that would seem a little tighter. But, as I think you were
suggesting, it's probably no faster to have .NET perform that lookup,
assuming the run-time lookup can't be avoided.

class AffiliateFeedFactory
{
private class AffiliateType
{
public AffiliateType(string name, Type type)
{
Name = name;
Type = type;
}
public string Name { get; set; }
public Type Type { get; set; }
}

private static AffiliateType[] AffiliateTypes = {
new AffiliateType("RegNow", typeof(AffiliateFeedRegNow)),
// AffiliateFeedRegNow inherits from AffiliateFeed
// Additional types go here...
};

public static AffiliateFeed GetInstance(string affiliate)
{
for (int i = 0; i < AffiliateTypes.Length; i++)
{
if (String.Compare(AffiliateTypes.Name, affiliate, true) == 0)
return
(AffiliateFeed)Activator.CreateInstance(AffiliateTypes.Type);
}
return null;
}
}

Thanks.

Jonathan
 
P

Peter Duniho

Jonathan said:
Yeah, the code below is what I'm playing with so far. If I could avoid
the lookup, that would seem a little tighter. But, as I think you were
suggesting, it's probably no faster to have .NET perform that lookup,
assuming the run-time lookup can't be avoided.

The lookup in your GetInstance() method is completely inconsequential
compared to the cost of calling the Activator.CreateInstance() method.
The latter is very expensive. Much, much more expensive than just using
the "new" operator when you know the type name at compile time.

There's nothing in your example that suggests that you need the
Activator.CreateInstance() method. Since you hard-code the registered
types, those types are obviously known at compile time. You could (and
should, based on the information so far) just as easily code a "new"
operator rather than calling CreateInstance().

Your code example could just look like this:

class AffiliateFeedFactory
{
public static AffiliateFeed GetInstance(string affiliate)
{
switch (affiliate)
{
case "RegNow":
return new AffiliateFeedRegNow();
default:
return null;
}
}
}

Easier to maintain, and MUCH faster at run-time.

Note that the C# compiler is reasonably good at producing efficient
implementations for the "switch" statement, and the JIT compiler may be
able to improve things further. A "switch" statement is actually a
pretty good, simple, readable way to represent this sort of one-off mapping.

Obviously if you needed to manipulate the mapping at run-time in other
ways – for example, adding new items, or examining it for purposes other
than doing the mapping – some other data structure might be more
appropriate. But even there, there's no need to use reflection. For
example:

class AffiliateFeedFactory
{
private static Dictionary<string, Func<AffiliateFeed>>
AffiliateTypes;

static AffiliateFeedFactory()
{
AffiliateTypes = new Dictionary<string, Func<AffiliateFeed>>();

AffiliateTypes.Add("RegNow", () => return new AffiliedFeedRegNow());
}

public static AffiliteFeed GetInstance(string affiliate)
{
Func<AffiliateFeed> func;

if (AffiliateTypes.TryGetValue(affiliate, out func))
{
return func();
}

return null;
}

public static IEnumerable<AffiliateFeed> GetAffiliateNames()
{
foreach (string affiliate in AffiliateTypes.Keys)
{
yield return affiliate;
}
}
}

With that example, the factory can easily return a complete list of all
the known affiliate names. You can, of course, add additional
functionality as needed. The main point of the example is to show how a
data structure that maps from a string to a delegate that can create an
instance of the desired class can be created, and then used in ways
other than just to instantiate the types involved.

Pete
 
P

Peter Duniho

Peter said:
[...]
public static IEnumerable<AffiliateFeed> GetAffiliateNames()
{
foreach (string affiliate in AffiliateTypes.Keys)
{
yield return affiliate;
}
}
[...]

Of course, my "GetAffiliateNames()" should return an
"IEnumerable<string>" and not an "IEnumerable<AffiliateFeed>".

Sorry for the goof.

Pete
 
J

Jonathan Wood

Peter Duniho said:
Note that the C# compiler is reasonably good at producing efficient
implementations for the "switch" statement, and the JIT compiler may be
able to improve things further. A "switch" statement is actually a pretty
good, simple, readable way to represent this sort of one-off mapping.

For things like this, I generally prefer a table. Of course, my background
is in C++ where tables can be EXTREMELY efficient for things like this,
while C# can be very different.
Obviously if you needed to manipulate the mapping at run-time in other
ways – for example, adding new items, or examining it for purposes other
than doing the mapping – some other data structure might be more
appropriate. But even there, there's no need to use reflection. For
example:

class AffiliateFeedFactory
{
private static Dictionary<string, Func<AffiliateFeed>>
AffiliateTypes;

I like this a lot, and I'll just take your word for it that it would be much
faster than Activator.CreateInstance().

While I enjoy static tables where the data is initialized in the EXE image,
C# doesn't really support that anyway. And so calling the Add method to
build the collection would not appear to be a disadvantage.

I'll give that a go. (And yield is another new one for me.)

Thanks!

Jonathan
 
J

Jonathan Wood

Peter Duniho said:
AffiliateTypes.Add("RegNow", () => return new AffiliedFeedRegNow());

I'm definitely liking this. However, I can't seem to get this syntax to work
for me.

I tried adding a type cast like this:

AffiliateTypes.Add("RegNow", () => return (AffiliateFeed)new
AffililiateFeedRegNow());

But the compiler still complains that I have an invalid argument.

Any thoughts?

Jonathan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top