Archived

This topic is now archived and is closed to further replies.

joanusdmentia

C# reflection with manually loaded assemblies

Recommended Posts

joanusdmentia    1060
I'm currently trying to create an object whose type is specified as a string. I use Type.GetType(typestr) with a type in the currently executing assembly and all is good. However, I'm using a plugin system where I manually load some assemblies using Assembly.LoadFrom(), and whenever typestr is a type in a loaded assembly GetType() fails (returns null). This is basically what I'm doing:
Assembly assembly = Assembly.LoadFrom("Plugin.Assembly.dll");
string typename = assembly.GetTypes()[0].AssemblyQualifiedName;
Type type = Type.GetType(typename);
 
What I'm actually doing is using the AssemblyQualifiedName to store the object type in a save file. When I load the file back up I use this to recreate the object and then fill the objects data in with the data that follows in the save file. As a last resort I could probably call GetType() for every loaded assembly myself but from what I could gather from the documentation this should work. [edited by - joanusdmentia on August 6, 2003 11:11:24 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
What are you trying to do??? To me it seems like you should use serialization instead.

Share this post


Link to post
Share on other sites
Tylon    181
Type.GetType only works on the statically present types in your project. It will not get you a type from an assembly thats only present in one of your Assembly variables.

To get a type from an assembly, you have to use Assembly.GetTypes again, and check whether each types name is the type you are looking for.

Then use Activator.CreateInstance(type); to create an instance of that object.

Share this post


Link to post
Share on other sites
joanusdmentia    1060
quote:

What are you trying to do??? To me it seems like you should use serialization instead.


I''m writing out and reading back a structure somewhat like a scenegraph. I did try using XmlSerializer, but it seems like using it with recursive data types is more trouble than just doing it all myself. Also, if I''m deserializing a type that might be in an assembly loaded with LoadFrom() would that even work? If I''m missing something here please let me know!

quote:

Type.GetType only works on the statically present types in your project. It will not get you a type from an assembly thats only present in one of your Assembly variables.


That''s annoying
Easy enough to get around though. Thanks for your help.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
quote:
Original post by joanusdmentia
quote:

What are you trying to do??? To me it seems like you should use serialization instead.


I''m writing out and reading back a structure somewhat like a scenegraph. I did try using XmlSerializer, but it seems like using it with recursive data types is more trouble than just doing it all myself.
quote:
I really think you should do it the "right" way, it shouldn''t be impossible or too hard. If you post a small testable sample of what you want to do it''s easier to help.

One reason to not use reflection is that it won''t work in many scenarios. Reflection requires ReflectionPermission, which many users might not have if admins has restricted permissions (which will be more and more common).

Share this post


Link to post
Share on other sites
joanusdmentia    1060
quote:

I really think you should do it the "right" way, it shouldn''t be impossible or too hard. If you post a small testable sample of what you want to do it''s easier to help.

One reason to not use reflection is that it won''t work in many scenarios. Reflection requires ReflectionPermission, which many users might not have if admins has restricted permissions (which will be more and more common).


Hmm, wasn''t aware of that. That really isn''t an issue for me though since my plugin system relies on reflection, so my app would really be screwed anyway . For the time being at least I''ll simply be happy to get this working.

A simplified version of the data structure is

public abstract class SceneGraphNode : Named
{
public SceneGraphNode() {}
public SceneGraphNode(string name) : base(name) {}

private SceneGraphNode parent = null;
[XmlIgnore]
public SceneGraphNode Parent
{
get { return parent; }
}

private ArrayList children = new ArrayList();
public ArrayList Children
{
get { return children; }
}

protected Math.Vector position = new Math.Vector();
public Math.Vector Position
{
get { return position; }
set { position = value; }
}

protected Math.Vector rotation = new Math.Vector();
public Math.Vector Rotation
{
get { return rotation; }
set { rotation = value; }
}
}

My problem was that attempting to serialize the object would go into an infinite loop, even with [XmlIgnore] applied to the Parent property. I tried playing with it but after a little while I gave up and decided to go with reflection. How would you go about serializing this? And would this work correctly when the type being serialized is derived from SceneGraphNode and exists in an assembly loaded with Assembly.LoadFrom()?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I haven''t done this myself, so I cannot help much more. I''d guess you need to implement ISerializable. I think Microsoft''s news server is a better place to look for help about this:

http://groups.google.com/groups?q=microsoft.public.dotnet.xml

or

http://msdn.microsoft.com/newsgroups/default.asp?url=/newsgroups/loadframes.asp?icp=msdn&slcid=us&newsgroup=microsoft.public.dotnet.xml



quote:
Original post by joanusdmentia
...my plugin system relies on reflection...
Not sure what you''re doing... ;-) But if you''re doing some sort of executable and allow 3rd parties to write plugin to your code, I don''t think you need reflection. Simply have an interface assembly, where you define the interfaces they need to implement. Then have a config file telling what assemblies/classes you need to load, containing the implementations of your interfaces.

Share this post


Link to post
Share on other sites
VizOne    598
quote:
Original post by Tylon
Type.GetType only works on the statically present types in your project. It will not get you a type from an assembly thats only present in one of your Assembly variables.



Check out the AppDomain.TypeResolve and AppDomain.AssemblyResolve events. You can help the CLR to resolve types and assemblies!

Regards
VizOne

[edited by - VizOne on August 7, 2003 12:58:57 PM]

Share this post


Link to post
Share on other sites
Arild Fines    968
quote:
Original post by Anonymous Poster
I don''t think you need reflection. Simply have an interface assembly, where you define the interfaces they need to implement. Then have a config file telling what assemblies/classes you need to load, containing the implementations of your interfaces.

And this would get around the need for reflection how?



AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
As I interpret "plugin system", it''s a way to provide 3rd parties to implement some functionality so your application can use it without knowing how it''s implemented.

If so, you could expose an interface in an assembly, and the 3rd party can reference that assembly and implement that interface. There''s no need to use reflection.

But joanusdmentia''s plugin system is maybe something else than this, in which case reflection might be needed.

The reason I''m wondering if reflecion is necessary, is that I''ve seen few cases where it really is needed. It''s a really powerful and cool feature! I''ve used it a lot for testing, but rarely used it in production code.

Share this post


Link to post
Share on other sites
Arild Fines    968
quote:
Original post by Anonymous Poster
As I interpret "plugin system", it''s a way to provide 3rd parties to implement some functionality so your application can use it without knowing how it''s implemented.

If so, you could expose an interface in an assembly, and the 3rd party can reference that assembly and implement that interface. There''s no need to use reflection.


But the plugin would still need to be loaded into the host application in some way, and that WOULD require reflection.



AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
quote:
Original post by Arild Fines
But the plugin would still need to be loaded into the host application in some way, and that WOULD require reflection.
Of course you''re right. I must have left my brain at home yesterday ;-)

Share this post


Link to post
Share on other sites
joanusdmentia    1060
AP, thanks for the links, I''ll check them out. I think I''ll probably just continue down my current path for now though and give serialization another shot later.

quote:

Check out the AppDomain.TypeResolve and AppDomain.AssemblyResolve events. You can help the CLR to resolve types and assemblies!


Thanks, that''ll help heaps!

Share this post


Link to post
Share on other sites
the Speed Bump    240
Here''s what I do:

    // Use reflection to check this app at runtime, and yank out all the classes that implement

// IEditorTool, then stuff them in the toolbox.

// If there are no tools in this EXE (?!) the function throws an exception.

// So the caller can always assume that at least one tool is returned.

// IEditorTool is defined in a separate assembly, that can be referenced

// by plugin assemblies.

IEditorTool[] GetTools()
{
ArrayList l = new ArrayList();

Type tooltype = typeof(IEditorTool);

// tweak this to load other assemblies, obviously

foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (tooltype.IsAssignableFrom(t))
{
ConstructorInfo c = t.GetConstructor(Type.EmptyTypes);
if (c != null)
l.Add(c.Invoke(null));
}
}

if (l.Count == 0)
throw new Exception("No tools! @_@");

return (IEditorTool[])l.ToArray(typeof(IEditorTool));
}


I''m hip because I say "M$" instead of "MS".

Share this post


Link to post
Share on other sites