How to approach constructing an instance of an unknown class?

K

K Viltersten

I have a class that reads an XML and
according to its contents, it creates a
List<Letter>, where Letter is an abstract
class that is implemented in Alpha and
Beta classes.

I use a foreach statement consisting of a
switch upon which i create an instance of
e.g. Alpha an add it to the list.

The only limitation is that if i ever
invent a new implementation, say Gamma,
i'll be forced to rewrite, recompile and
reinstall the executable.

I'm looking for a suggestion on how to
approach the problem so that a new type
will be handled appropriately (provided
that i distribute SOME definition of the
appropriate actions to be taken).
 
P

Peter Morris

You could have an app.config file

<classes>
<add key="Alpha" value="MyNameSpace.MyClass, MyAssemblyName"/>
<add key="Beta" value="MyNameSpace.MyClass2, MyAssemblyName"/>
<add key="Gamma" value="MyNameSpace.MyClass3, NameOfMyNewAssembly"/>
</classes>

You can read these in and add them to a Dictionary<string, Type>, then you
can easily create instances based on the name. This way you can drop a new
DLL into the folder + update the app.config and you are all done.



Pete
 
P

Pavel Minaev

K Viltersten said:
I have a class that reads an XML and
according to its contents, it creates a
List<Letter>, where Letter is an abstract
class that is implemented in Alpha and
Beta classes.

I use a foreach statement consisting of a
switch upon which i create an instance of
e.g. Alpha an add it to the list.

The only limitation is that if i ever
invent a new implementation, say Gamma,
i'll be forced to rewrite, recompile and
reinstall the executable.

I'm looking for a suggestion on how to
approach the problem so that a new type
will be handled appropriately (provided
that i distribute SOME definition of the
appropriate actions to be taken).

Sounds like a classic case for the abstract factory pattern. For instance,
let's say that you decide on the class to use depending on the name of the
XML element that you encounter. Then, you abstract away the logic of
creating a letter of specific type from an XML node as a delegate (or an
interface), and introduce a registry (could be one, could be several) for
known implementations of that interface/delegate.

delegate Letter LetterFactory(XElement element);
Dictionary<XName, LetterFactory> Factories;

List<Letter> ParseLetters(XDocument document)
{
XElement current;
...
var factory = Factories[current.Name];
var letter = factory(current);
...
}

...

Alpha AlphaLetterFactory(XElement element)
{
Alpha result = ...; // create and fill from XML
return result;
}

Factories.Add("alpha", AlphaLetterFactory);

...

Beta BetaLetterFactory(XElement element)
{
Beta result = ...; // create and fill from XML
return result;
}

Factories.Add("beta", BetaLetterFactory);

...

XDocument doc = ...;
ParseLetters(doc);
 
M

Marc Gravell

Only one
question, regarding the var keyword. Is
it allowed even in DotNet 2.0?

Yes, but it needs C# 3.0 (the language and the .NET library version are
separate). In this case it probably just saves a little typing. The only
*essential* use of var is with anonymous types, which are a C# 3.0 feature.

Marc
 
K

K Viltersten

I have a class that reads an XML and
according to its contents, it creates a
List<Letter>, where Letter is an abstract
class that is implemented in Alpha and
Beta classes.

I use a foreach statement consisting of a
switch upon which i create an instance of
e.g. Alpha an add it to the list.

The only limitation is that if i ever
invent a new implementation, say Gamma,
i'll be forced to rewrite, recompile and
reinstall the executable.

I'm looking for a suggestion on how to
approach the problem so that a new type
will be handled appropriately (provided
that i distribute SOME definition of the
appropriate actions to be taken).

Sounds like a classic case for the abstract factory pattern. For instance,
let's say that you decide on the class to use depending on the name of the
XML element that you encounter. Then, you abstract away the logic of
creating a letter of specific type from an XML node as a delegate (or an
interface), and introduce a registry (could be one, could be several) for
known implementations of that interface/delegate.

delegate Letter LetterFactory(XElement element);
Dictionary<XName, LetterFactory> Factories;

List<Letter> ParseLetters(XDocument document)
{
XElement current;
...
var factory = Factories[current.Name];
var letter = factory(current);
...
}

...

Alpha AlphaLetterFactory(XElement element)
{
Alpha result = ...; // create and fill from XML
return result;
}

Factories.Add("alpha", AlphaLetterFactory);

...

Beta BetaLetterFactory(XElement element)
{
Beta result = ...; // create and fill from XML
return result;
}

Factories.Add("beta", BetaLetterFactory);

...

XDocument doc = ...;
ParseLetters(doc);

Oh, i think i see the approach. Only one
question, regarding the var keyword. Is
it allowed even in DotNet 2.0? I fear
that it's a newer thing, like 3.0 or 3.5
and such great utilities i can't use. :(
 
J

Jon Skeet [C# MVP]

Oh, i think i see the approach. Only one
question, regarding the var keyword. Is
it allowed even in DotNet 2.0? I fear
that it's a newer thing, like 3.0 or 3.5
and such great utilities i can't use. :(

"var" is part of C# 3.0, but you can still use it when targeting .NET
2.0 from VS2008. However, it's unnecessary anyway - unless you're using
anonymous types (another part of C# 3.0) you can always just use the
real name instead of "var". It's just the compiler inferring the type
for you.
 
P

Peter Morris

This approach wont solve the problem you described, in particular

========
The only limitation is that if i ever
invent a new implementation, say Gamma,
i'll be forced to rewrite, recompile and
reinstall the executable.
========
 

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