Pass type to method to allow create and method invocation?

G

Grant Schenck

Hello,

I have a base class with several derived classes:
ScriptBase
+ ScriptCallInbound
+ ScriptCallOutbound

I then have another class:
Line

Line has a method:
DoExecute()

What I want DoExecute to do be passed a type (ScriptCallInbound or
ScriptCallOutbound) and be able to call an Execute() method defined in the
ScriptBase as virtual and supplied by the derived classes.

So, I assume the DoExecute() method would need to accept some kind of type
of a ScriptBase derived class that it could then create a new instance of
and invoke the Execute() method. I want both the NEW and Execute() methods
to be handled by the actual type passed.

How do I go about doing this in C#?

Thanks,

Grant Schenck
 
D

DeveloperX

Hello,

I have a base class with several derived classes:
ScriptBase
+ ScriptCallInbound
+ ScriptCallOutbound

I then have another class:
Line

Line has a method:
DoExecute()

What I want DoExecute to do be passed a type (ScriptCallInbound or
ScriptCallOutbound) and be able to call an Execute() method defined in the
ScriptBase as virtual and supplied by the derived classes.

So, I assume the DoExecute() method would need to accept some kind of type
of a ScriptBase derived class that it could then create a new instance of
and invoke the Execute() method. I want both the NEW and Execute() methods
to be handled by the actual type passed.

How do I go about doing this in C#?

Thanks,

Grant Schenck

You after something like this?

using System;

namespace WindowsApplication23
{
public class ScriptBase
{
public virtual void Execute()
{
Console.WriteLine("ScriptBase.Execute");
}
}
public class ScriptCallInbound : ScriptBase
{

public override void Execute()
{
Console.WriteLine("ScriptCallInbound.Execute");
}
}
public class ScriptCallOutbound : ScriptBase
{

public override void Execute()
{
Console.WriteLine("ScriptCallOutbound.Execute");
}
}
public class Line
{
public void DoExecute(Type pType)
{
try
{
ScriptBase s = (ScriptBase)Activator.CreateInstance(pType);
s.Execute();
}
catch(Exception e)
{
//not an out or in bound. do what you have to
}
}
}
public class Test
{
public void TestIt()
{
Line l = new Line();
l.DoExecute(typeof(ScriptCallInbound));
l.DoExecute(typeof(ScriptCallOutbound));
}
}
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Grant Schenck said:
Hello,

I have a base class with several derived classes:
ScriptBase
+ ScriptCallInbound
+ ScriptCallOutbound

I then have another class:
Line

Line has a method:
DoExecute()

What I want DoExecute to do be passed a type (ScriptCallInbound or
ScriptCallOutbound) and be able to call an Execute() method defined in the
ScriptBase as virtual and supplied by the derived classes.


The method can use a ScriptBase as its parameter, then as the method is
virtual it will execute the correct version based on the type of the
instance being passed.
 
U

UL-Tomten

public void DoExecute(Type pType)

If you want compile-time type safety, as well as some cuddly framework
comfort, you could make DoExecute a generic method like so:

public void DoExecute<TScript>() where TScript : TScriptBase

Also, passing the Type of an instance to DoExecute() and then creating
a new instance sounds like throwing one instance away. Perhaps passing
the actual instance to DoExecute() in the first place would be
applicable here.
 
D

DeveloperX

If you want compile-time type safety, as well as some cuddly framework
comfort, you could make DoExecute a generic method like so:

public void DoExecute<TScript>() where TScript : TScriptBase

Also, passing the Type of an instance to DoExecute() and then creating
a new instance sounds like throwing one instance away. Perhaps passing
the actual instance to DoExecute() in the first place would be
applicable here.

I'm in the office at the moment, so only got 1.1 :(

Would that work? I read that as TScript must implement TScriptBase,
but we're passing in a class of type Type which does not.
My knowledge might be muddied by the fact that it's a type of type
Type and Type might expose something that where understands...
 
G

Grant Schenck

Well, just to muddy the water, I want to create an instance of the passed
type and be able to pass parameters. In my example, Script is an abstract
base class and Execute() is abstract.

So, I want to be able to do something like:

// Script's constructor
Script(int nID, string nName)
{...

// ScriptInbound Derived from
ScriptInbound : Script
{
public Override void Execute()
{...

ScriptOutbound : Script

DoExecute(Type pType, int nID, string nName)
{
// Not sure how I do...
Script script = new pType(nID, nName);

script.Execute();
}

THANKS!
 
U

UL-Tomten

Would that work? I read that as TScript must implement TScriptBase,
but we're passing in a class of type Type which does not.

Well, I would certainly recommend against passing a Type, because it
seems like something you would only do if late binding was your only
option. I got the impression your class hierarchy and its uses was
known at runtime, in which case the compiler and the CLR could do all
that work for you. But since I haven't the faintest clue about what
the bigger picture is, maybe a Type is what you need.
My knowledge might be muddied by the fact that it's a type of type
Type and Type might expose something that where understands...

No, I was only assuming a usage along the lines of, say:

DoExecute<ScriptCallInbound>(myScriptCallInbound);

Instead of passing a Type to DoExecute() and creating an instance
inside the method, wouldn't it make more sense to create an instance
outside the method and pass that?
 
D

DeveloperX

Well, I would certainly recommend against passing a Type, because it
seems like something you would only do if late binding was your only
option. I got the impression your class hierarchy and its uses was
known at runtime, in which case the compiler and the CLR could do all
that work for you. But since I haven't the faintest clue about what
the bigger picture is, maybe a Type is what you need.


No, I was only assuming a usage along the lines of, say:

DoExecute<ScriptCallInbound>(myScriptCallInbound);

Instead of passing a Type to DoExecute() and creating an instance
inside the method, wouldn't it make more sense to create an instance
outside the method and pass that?

Oh ok, I didn't realise you were re-architecting it :) Speaking of
which I sort of agree with you, but without knowing the OP's reasons
for wanting to create the object in DoExecute we can't really say. If
it's possible to create it outside it certainly makes sense for the
reasons you''ve listed above.

Grant, I'm on a train at the moment, but from memory CreateInstance
has overloads which allow arrays of parameters to be passed in. If you
can't get it to work I'll take a look as soon as I can if someone else
doesn't get there before me :)
 
G

Grant Schenck

That's fine, I have it working without parms by using a base initialize
method. I can look at passing parms.

I'm certainly open to a better mouse trap on this.

My GOAL is as follows:

I'm developing a class library for an phone system IVR (interactive voice
response.) It is based on a COM object which internally uses the PBX's TAPI
Interface.

The DoExecute() method on the base class creates a thread, associates it
with the class and then calls an Execute() method provided by the derived
class. This method can then carry out the work of the IVR "script" in a
synchronous fashion.

The idea is that I can define an IVR script which is run when a new call
presents and can then answer, play audio, capture digits, transfer, etc the
call. This way the thread can block for each stage of the IVR to complete.

The individual stages (answer call, play audio to caller and collect digits,
etc.) all block waiting for an event while the underlying COM object carries
them out. These stages are coded as methods in the base class and are used
by the derived classes execute methods to actually do work.

SO... I want to package the class as a separate C# library and then be able
to link with the libary from typically a Windows Service app and be able to
just create a class derived from Script with an Execute method to do the
actual work of the script.

Hope that makes sense...?
 
G

Grant Schenck

No because the class needs to be able to create instances of the specified
type in response to external events (in this case, phone calls.)

So, this class is to monitor one line or port of a phone system's
interactive voice response unit. The class wants to respond to inbound
calls by creating a script object to interact with the caller (the script
spins off a thread) FOR EACH CALL.
 
U

UL-Tomten

No because the class needs to be able to create instances of the specified
type in response to external events (in this case, phone calls.)

It still sounds like you could use type safe instance creation, like:

DoExecute<TScriptCall>() where TScriptCall : ScriptCallBase {
TScriptCall scriptCall = new TScriptCall();
scriptCall.OverriddenMethod();
}

....and invoke it thusly:

DoExecute<ScriptCallInbound>();

My point is that compile-time type safety in my experience usually
saves nine.
 

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