Dynamically bring in a class?

  • Thread starter TheVillageCodingIdiot
  • Start date
T

TheVillageCodingIdiot

I'm working on a vb.net application that handles billing reports.
Every client has a different way they want to see the reports. The
data exists in a sql 2005 db and the billing report will be in a excel
file. One option I was thinking about was to create a custom class for
each company and have my application import it dynamically. Is this
possible in vb.net 2005? If so how would you do this?

Thank you
 
J

Jon Skeet [C# MVP]

TheVillageCodingIdiot said:
I'm working on a vb.net application that handles billing reports.
Every client has a different way they want to see the reports. The
data exists in a sql 2005 db and the billing report will be in a excel
file. One option I was thinking about was to create a custom class for
each company and have my application import it dynamically. Is this
possible in vb.net 2005? If so how would you do this?

Use Type.GetType, specifying the full type name including the assembly.
You can then create an instance of the type, which should probably
implement a common interface. Cast to the interface then use the
instance appropriately.
 
S

sloan

http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!126.entry

Check that blog .. with special emphasis on #3 (Reflection).

This is another option, but I think it makes sense with your scenario. (what
what I can gather).

.......

But itd be nice to get some clarification.

Is the DATA (tables in sql server) the SAME among the clients, and they only
want a different presentation layer (look/feel of the reports).

OR

Is the DATA (DDL/tables) different, AND they have different needs for the
presentation layer.

OR

Is the DATA (DDL/tables) different, but they essentially have the same
presenation of reports (look feel, etc).
 
T

TheVillageCodingIdiot

Could you maybe show me a sample code. I'm a little new to .NET and it
would be greatly appreciated.

Thank you
 
T

TheVillageCodingIdiot

sloan,

the data in the table is the same for all companies. The customers
just want the excel in different formats. For example some want to see
the bill grouped by different health plans with a sum for each plan,
others want it grouped by there company's departments, other want it
in alphebetical by last name and so forth.
 
J

Jon Skeet [C# MVP]

TheVillageCodingIdiot said:
Could you maybe show me a sample code. I'm a little new to .NET and it
would be greatly appreciated.

To be honest, if you're new to .NET I'd walk before you can run - I
could give you some code, but then if you ran into any problems with it
you'd quite possibly have a hard time understanding the error messages.

This kind of thing can get quite tricky quite quickly.
 
T

TheVillageCodingIdiot

If you could that would be great. That is how I have learned as much
as I have so far. I get in over my head and play with it till I know
it. I love a good puzzle :D
 
S

Scott Roberts

TheVillageCodingIdiot said:
I'm working on a vb.net application that handles billing reports.
Every client has a different way they want to see the reports. The
data exists in a sql 2005 db and the billing report will be in a excel
file. One option I was thinking about was to create a custom class for
each company and have my application import it dynamically. Is this
possible in vb.net 2005? If so how would you do this?

Thank you


Here is some C# code we use. As Jon mentioned in his post, each type
implements a common interface. Furthermore, this code assumes that there is
a default constructor (no parameters). I modified the code after pasting
into this message, so please forgive any typos that may cause it to not
compile.

private IRawCallDetail GetParser(string assemblyName, string
typeName)
{
// Load the appropriate assembly.
Assembly asm = null;
try
{
asm = Assembly.Load(assemblyName);
}
catch (Exception ex)
{
throw new Exception("Error loading parser assembly.", ex);
}

// Get the parser type from the assembly.
Type parsertype = null;

try
{
parsertype = asm.GetType(typeName);
}
catch (Exception ex)
{
throw new Exception("Error locating parser type.", ex);
}

// Create an instance of the appropriate class.
try
{
return (System.Activator.CreateInstance(parsertype) as
IRawCallDetail);
}
catch (Exception ex)
{
throw new Exception("Error creating parser.", ex);
}
}
 
S

sloan

The reflection samples...are available at my blog...and are the same thing
Jon and Scott are speaking of.

....

My architecture for this scenario.

Reports
Same Baseline Data.
Different presentation needs per customer.

....................

Create STRONG datasets to represent mini portions of the data you need.
(This will become important as you pick which presentation layer you use)

Create a several strong datasets...for each need (not how it looks, but just
the data you need).

BillingByHealthPlanDS
BillingByCompanyDS
BillingByCustomerDS

You're doing this so you can get REUSE from these.

Write code to pull data (stored procedure?) and populate each of the DS's
above.

...........

THEN, lets say you have 2 customers..and each one wants to see the 3 sets of
data above in a different format.
(Let's pretend one likes white background, and one likes pink background)


IReport
--DisplayReport
--SetDataSource( DataSet ds );

IHealthPlanReport : IReport
--DisplayReport (comes from the previous interface)

IHealthPlanReport : IReport
--DisplayReport (comes from the previous interface)

ICompanyReport : IReport
--DisplayReport (comes from the previous interface)

ICustomerReport : IReport
--DisplayReport (comes from the previous interface)



The DisplayReport method will be the code which actually generates the
Excel (or whatever) you need.

You'll write 2 concretes for each of the 3 interfaces:

Company1HealthPlanReport : IHealthPlanReport
Company2HealthPlanReport : IHealthPlanReport

Company1CompanyReport : ICompanyReport
Company2CompanyReport : ICompanyReport

Company1CustomerReport : ICustomerReport
Company2CustomerReport : ICustomerReport


..........

I'm show one of the reports code:

public class Company1CustomerReport : ICustomerReport
{
private BillingByCustomerDS _modelDS = null;

public voic SetDataSource(DataSet ds)
{
this._modelDS = ds as BillingByCustomerDS;
if(null==this._modelDS)
{
throw new ArgumentNullException("DS was null, or the WRONG concrete type of
DataSet");
}
}


public void DisplayReport ()
{

//some how use _modelDS ...to create Excel AND give it a WHITE
backgroud, not pink
Console.WriteLine( _modelDS.GetXml());//<<the crappiest "Show Report"
method you'll ever see

}

}



Now you can use my blog article..and use reflection to load one of the
concretes...per Company.

I know it doesn't map perfectly like that...BUT you've got some ideas now.


By putting work into the strong dataset creation..you get reuse.

Then your code can be something like this:



BillingByCustomerDS ds = new BillingByCustomerDS(); // use something like
LoadDataSet to actually populate values)
IReport rpt1 = new Company1CustomerReport();
rpt1.SetDataSource(ds);
rpt1.DisplayReport();


And where I have
IReport rpt1 = new Company1CustomerReport();
you'll replace with some kind of reflection code (per my blog).
Or you might use the "By Key" method as well, and pass in the specific
customerID.

You need to work through my example blog code (downloadable) and actually
work with it some.

OO and interfaces aren't something you just "get" in one sitting.

Good luck.


You can also research the "Crystal Reports PUSH method" as well.
It will give you some clues as to why putting data into strong datasets..and
then PUSHING them into a report is a better plan of attack.
Even if you're NOT using Crystal Reports..it doesn't matter. The concepts
are good.

And if you ever decide to do something like
ActiveReports, Crystal Reports....then all that work you did with strong
datasets is reusable.
do NOT use the "pull" method.

..........

Outside of all that, you might consider Active Reports, since they have
pretty good licensing AND exporting features (to excel is one of them).


Now send my consulting free to my paypal account!! ([email protected])
(ha ha)


If you don't know how to create a strong dataset or POPULATE a strong
dataset, check my blog entry "1.1 Custom Business Objects".
Ignore the customer business objects, and check the sample strong datasets,
tsql, and LoadDataSet methods I use.
 
T

TheVillageCodingIdiot

Thank to everyone who helped me out. I played around it with the
code, have a new bald spot, and figured out how to use this the way I
need to. Took a little time to translate it to vb but hey, nothings
fun if its easy lol. TYVM. Sloan, glad to see your consulting free
lol :p
 
C

Cowboy \(Gregory A. Beamer\)

Yes, it is possible.

Instead of dynamic, however, I think you should look at the idea of the
provider model, like Microsoft does with Membership, etc. You then configure
for the client in the config.

Now, this is fairly impossible if you are running the precise same
application (meaning you are running all the clients on a single instance at
your location rather than each client gets a copy). In that instance, you
can create a common interface and add a factory pattern on top of the
different client implementations. You then instantiate the object, with the
interface, that fits the client at hand.

In fact, I would opt for a factory method regardless of whether you lock the
object down in config (client side implementation) as it makes it easier for
you to test your software for all clients on your local box.

--
Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

*************************************************
| Think outside the box!
|
*************************************************
 
C

Cowboy \(Gregory A. Beamer\)

I don't think he has to go to this level right now. I could be wrong, but
the description sounds like it is a perfect use of a factory pattern, using
an interface as the "instantiated object" (in quotes, as you are not
actually instantiating an interface ;->). In terms of complexity, this would
be much easier than dynamic instantiation of objects and less error prone
for someone starting out.

--
Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

*************************************************
| Think outside the box!
|
*************************************************
 
S

sloan

My blog shows the Factory Pattern, via a "Key" or via Reflection.

So I think he can pick which one makes sense for his need.

But yeah....Reflection might be overkill for this.

You can start with the "Key" and then move up to Reflection if need be.

...........

http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!126.entry


But I agree with you, start with a simpler Factory approach.
Then you can go to reflection if that doesn't work.




Cowboy (Gregory A. Beamer) said:
I don't think he has to go to this level right now. I could be wrong, but
the description sounds like it is a perfect use of a factory pattern, using
an interface as the "instantiated object" (in quotes, as you are not
actually instantiating an interface ;->). In terms of complexity, this
would be much easier than dynamic instantiation of objects and less error
prone for someone starting out.

--
Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

*************************************************
| Think outside the box! |
*************************************************
 
C

Cowboy \(Gregory A. Beamer\)

When I go through applications for refactoring, I often find someone
reflecting for dyanmic loading when it is not necessary. One of two reasons:

1. Kewl thing to learn (and I mean kewl, not cool) ;-)
2. Only have a hammer and everything is a nail

There are definitely times when you need Reflection. Even times when you
need to Emit via Reflection. But most times you can load up a simple factory
pattern and use a "less dynamic" approach than Reflection. In fact, almost
every time I have seen Reflection used, it has been done on a problem that
could be solved with a simple factory pattern.

Now, as far as learning goes, I think you should learn as much as possible.
Understanding the variety of tools available gives you more options. You
also learn when not to go complex. I would say it follows the 80-20 rule:
80% of the time, when you have a complex problem, there is a simple
solution. :)

--
Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

*************************************************
| Think outside the box!
|
*************************************************
sloan said:
My blog shows the Factory Pattern, via a "Key" or via Reflection.

So I think he can pick which one makes sense for his need.

But yeah....Reflection might be overkill for this.

You can start with the "Key" and then move up to Reflection if need be.

..........

http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!126.entry


But I agree with you, start with a simpler Factory approach.
Then you can go to reflection if that doesn't work.
 

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