How to get an assembly from a type string

  • Thread starter Thread starter Markus
  • Start date Start date
M

Markus

Hello all,

I am working on coding a custom Formatter to be used to
export and restore property settings from objects on a
form in an easily edited text format. It's not true
serialization and deserialization because I'm not fully
describing objects or instantiating them during
deserialization (just storing and later setting properties
which meet certain Attributes).

The serialization works and now I am working on the
deserializing portion and am trying to figure out how to
obtain a type from a type string so I can read the data
back in.

The GetType() method only works for types which are
included in my assembly or if I explicitly obtain the
assembly - otherwise it returns null.

For example, my file would contain a line like:

"Size System.Drawing.Size {Width=40, Height=25}"

which would tell the code that this object's
property "Size" of type "System.Drawing.Size" has the
value "{Width...}"

I need to obtain a type object from "System.Drawing.Size"
to properly parse the data of this property.

So, is there any way to obtain the assembly of an object
derived from system based solely on its string? I don't
want a hard-coded solution because it would be preferable
if the code would work with future releases of the .NET
redistributable and also I don't want to look up the
correct dll for each property to make the method more
robust.

Here is a brief fragment which is as close as I got
(gleaned off another website):

string assemblyloc =
Environment.GetEnvironmentVariable("systemroot") +
"\\Microsoft.Net\\Framework\\v" +
System.Environment.Version.ToString()+
"\\System.Windows.Forms.dll";

assembly.LoadFrom(assemblyloc);

This code still has 2 problems: the dll file is hardcoded,
and the version string includes an additional field which
causes it to generate the incorrect path (my path
is: ...\Microsoft.NET\Framework\v1.0.3705\", but the value
returned by System.Environment.Version is 1.0.3705.xxxx -
this xxxx field would need to be removed to generate the
correct path).

Many thanks for any advice,
Markus

PS - as I type all this in, I came up with a possible
solution - which isn't a solution to the problem above,
but might work for me...

I will probably try to do things from the other end -
instead of getting type information from the system which
requires me to get its assembly, I could instead get it
from my own objects, since their type information is in my
assembly.

For example, my serialization Formatter might produce the
following:

"MyNamespace.MyClass 1 #"
"Size System.Drawing.Size {Width=1, Height=1}"

Where the first line describes the object, 1 indicates the
number of property entries for this object, and #
represents the object's ID property (used for persistence).

I can use reflection on "MyNamespace.MyObject" to get a
reference to this object's properties, then use "Size" to
obtain a reference to the various parts of its Size
property.

Still, I would be very interested if anyone has a solution
to the problem above. Thanks.
 
Just in case anyone is interested, the method I described
at the end of my original post works; I now have the types
of each property.

Now for the next wall - how to get the data back into the
property. If anybody has any ideas on the correct way to
write out and read back properties - or if this is even
possible I'd sure appreciate it.

For example, calling object.ToString() when object is a
Size results in, say, "{Width=10, Height=10}", but there
doesn't seem to be a way to get that data back into the
Size during "deserialization".

Thanks again for any ideas.
Markus
 
Markus,
So, is there any way to obtain the assembly of an object
derived from system based solely on its string?

I suggest that you store the full assembly and type name instead. You
can get it with Type.AssemblyQualifiedName, and it should let you get
the type back with Type.GetType() later on (assuming the assembly can
be found).

string assemblyloc =
Environment.GetEnvironmentVariable("systemroot") +
"\\Microsoft.Net\\Framework\\v" +
System.Environment.Version.ToString()+
"\\System.Windows.Forms.dll";

assembly.LoadFrom(assemblyloc);

This code still has 2 problems: the dll file is hardcoded,
and the version string includes an additional field which
causes it to generate the incorrect path (my path
is: ...\Microsoft.NET\Framework\v1.0.3705\", but the value
returned by System.Environment.Version is 1.0.3705.xxxx -
this xxxx field would need to be removed to generate the
correct path).

To solve the second problem, you could use
RuntimeEnvironment.GetRuntimeDirectory() instead.

For example, calling object.ToString() when object is a
Size results in, say, "{Width=10, Height=10}", but there
doesn't seem to be a way to get that data back into the
Size during "deserialization".

Perhaps you shouldn't rely on ToString() (which can return pretty much
anything), but rather write the property values in your own format
that you know how to parse back. You can get/set the properties with
Reflection (PropertyInfo.[G|S]etValue).



Mattias
 
Thank you for your suggestions.
I suggest that you store the full assembly and type name instead. You
can get it with Type.AssemblyQualifiedName, and it should let you get
the type back with Type.GetType() later on (assuming the assembly can
be found).

Wouldn't this require the same assemblies to be present?
e.g. if the object being described is part of a control or
other system assembly, the software would need to run with
the same redistributable on which it was developed? I was
hoping to get access to the assemblies which are currently
present. I am somewhat surprised that there doesn't seem
to be a straightforward way to get a type object from a
type string which describes a type of object currently
being used by the software (in other words, it must have
already been loaded somehow and the system should know
where the assembly is).
Perhaps you shouldn't rely on ToString() (which can return pretty much
anything), but rather write the property values in your own format
that you know how to parse back. You can get/set the properties with
Reflection (PropertyInfo.[G|S]etValue).

I'm now thinking along similar lines. I am wondering how
to navigate object structures to establish the "bottom"
level without developing an entire serialization system of
my own. Ideally, at the high-level I would just mark which
control properties I want to serialize through attributes
when coding the control and the formatter would take care
of the rest.

But for now, it would probably be easier for now to just
do the navigation manually (hard-code each sub-property
such as Height and Width instead of Size - in many cases
that also fixes the other problem since these sub-
properties are primitive types).

Do you know of any good source of information on how the
existing formatters navigate object structures /
techniques and helper methods that can be used when
writing a formatter?

Once again, thanks for the input.

Markus
 
Back
Top