Application Domain

  • Thread starter Thread starter David Chipping
  • Start date Start date
D

David Chipping

When building a plugin system for my app, I wanted the plugins to be
ran in their own application domain; however, after reading the
documentation, I am lead to believe that after the application domain
has been produced and the assemblies loaded inside of it; if I want to
create instances of types held in that domain, I will be given proxy
classes that marshal their requests between domain boundaries. So is
this marshaling efficient? My domains will be running in the same CLR
and have a reasonable dependence on speed, and hence I don't want the
system to suffer. Can someone allay my thoughts by telling me how this
procedure is being executed exactly?

Thanks very much,

-David
 
The thing you want to do will be implemented in the new MAF (Managed Addin
Framework ) from MS.

Yes, if you want to use object from the other domain it will marshalled.
While marshalling objects are serialized completely, or TransparentProxy is
introduced.
All this stuff introduces great overhead if your types are big enough.

Another way is not to use App domains for your plugins, you can utilize
simple LoadAssembly->GetType(....) functionality...

Here are the links, where you can get more information about this topic:
(watch for word wrap)
Marshalling - ( http://blogs.msdn.com/tq/archive/2005/10/06/478059.aspx )
MAF -
( http://blogs.msdn.com/tq/archive/2005/09/15/467714.aspx )
 
Hello David,
When building a plugin system for my app, I wanted the plugins to be
ran in their own application domain; however, after reading the
documentation, I am lead to believe that after the application domain
has been produced and the assemblies loaded inside of it; if I want to
create instances of types held in that domain, I will be given proxy
classes that marshal their requests between domain boundaries. So is
this marshaling efficient? My domains will be running in the same CLR
and have a reasonable dependence on speed, and hence I don't want the
system to suffer. Can someone allay my thoughts by telling me how this
procedure is being executed exactly?

As Vadym wrote, you'll face some serious marshalling when crossing appdomain
boundaries. However, the question is why do you want to do that in the first
place. Typically you would want to use that for security or reliability
reasons, since appdomains are separated from each other and you can simply
shutdown an appdomain if something got screwy. Is that one of your
requirements for your plugin framework? If yes, you might have to make the
trade-off.

Christoph
 
Actually, that isn't the case. The original thought was this (bare in
mind that we know this isn't the correct use of appdomains and it was
only one of the solutions I was following up), our plugins have
localisation support, we wanted to have the localisation support that
vs.net offers for form development usable from within our system,
however this used satellite assemblies with a forced directory
structure (en-GB, fr-BE etc) which we couldn't use. Putting these
plugins in a AppDomain with the base application set would of simply
allowed us to have these directory structures with these satiliate
assemblies in another place that wasn't the root of our application
.....

However now it seems almost defiantly apparent that an appdomain is not
suitable for this and I won't be using it :)

Any other tips for the localisation - plugin - vs.net problem would
always be appreciated of course.
 
Vadym said:
Yes, if you want to use object from the other domain it will
marshalled. While marshalling objects are serialized completely, or
TransparentProxy is introduced.
All this stuff introduces great overhead if your types are big enough.

While I agree that *some* marshalling will occur I don't think that it
has to be a problem.

If you are continually making calls across the appdomain boundary then
you'll get marshalling. This can be as simple as a few layers, but can
be more. The reason is that certain objects require 'contexts' and each
context will involve an extra layer when accessing that object through
marshalling.

However, you can design away some of the issues. If your plug-ins have a
single initialization routine with no parameters (a ctor or some other
method) then you'll just get a single marshalling. If the initializer
has takes MarshalByRefObject parameters, then they will be run in the
appdomain where they are created so you'll get marshalling whenever the
object is accessed. If the parameters are not MarshalByRefObject then
they'll be serialized and reconstituted in the destination appdomain.

Similarly with calling the plug-in. If the plug-in does one action then
marshalling will only occur when the plug-in is called. If the plug-in
has many methods, then you'll get marshalling when each method is
called.

Why do you want to use appdomains? Is it for code isolation? (In which
case you can probably get sufficient using appropriate exception guard
blocks around the calls to the plug-in.) Is it for separate
configuration files? (If so, then you could create your own
configuration mechanism.)

What's the plug-in architecture: is it a simple initialization followed
by a single method call; or is it a complicated initialization, followed
by many calls from the plug-in container? If the latter, can it be
simplified?

Richard
 
David said:
Actually, that isn't the case. The original thought was this (bare in
mind that we know this isn't the correct use of appdomains and it was
only one of the solutions I was following up), our plugins have
localisation support, we wanted to have the localisation support that
vs.net offers for form development usable from within our system,
however this used satellite assemblies with a forced directory
structure (en-GB, fr-BE etc) which we couldn't use.

You can change how this works. This is just the convention that
ResourceManager uses. A satellite 'assembly' is simply a localised file
that contains resources. You can load any resource file in code, so you
can write an equivalent of ResourceManager.

You can write an equivalent that, for example, expects the culture to be
encoded in the shortname. Note that satellite resources are not 'normal'
assemblies, they are not loaded by Fusion, they are loaded explicitly by
ResourceManager. Use Reflector to decompile this class, and look at how
it locates the DLL, then write you own version.
Putting these
plugins in a AppDomain with the base application set would of simply
allowed us to have these directory structures with these satiliate
assemblies in another place that wasn't the root of our application

Doesn't sound like a good solution to your problem.
However now it seems almost defiantly apparent that an appdomain is
not suitable for this and I won't be using it :)

Any other tips for the localisation - plugin - vs.net problem would
always be appreciated of course.

yes, handle it yourself :-)

Richard
 
Thanks very much for the response.

I had actually already disassembled the ResourceManager (and thusly now
in VS.NET the ComponentResourceManager). From what I could see, the
processed relating to loading Satellite assemblies was pretty
uncustomizable to the point of adapting our system to the directory
layout of sa loading, being much easier, which is what's happening.
 
David said:
Thanks very much for the response.

I had actually already disassembled the ResourceManager (and thusly
now in VS.NET the ComponentResourceManager). From what I could see,
the processed relating to loading Satellite assemblies was pretty
uncustomizable to the point of adapting our system to the directory
layout of sa loading, being much easier, which is what's happening.

I am not sure what you mean. Loading resources is pretty simple:

// typed without testing...
// get name of 'satellite', lets code the culture in the name
string name = "myApp_"+Thread.CurrentThread.CurrentUICulture.Name;
// load the assembly
Assembly assem = Assembly.LoadFrom(name + ".dll");
// assume the stream has the same name
Stream stm = assem.GetManifestResourceStream(name);
// its a compiled resource...
ResourceReader reader = new ResourceReader(stm);
// now access the resources through the reader

This is the basis of the solution to your problem.

Satellite assemblies do not have to be assemblies! Microsoft have chosen
to do that, but they did not have to. They *never* contain code. They
are *never* loaded with Fusion. The only advantage of them being
assemble is that they can be put in the GAC, but even then normal
versioning is not used. Read through the resources section of my Fusion
tutorial.

Richard
 
I appreciate the response, unfortunatly loading resource files through
ResourceReader isn't my problem:

My problem is that I wish to customise the manner in which the
ResourceManager class loads it's Satellite Assemblies for localisation,
as (for reason beyond this post) I have to use it for my localisation
resource handling. Currently, as far as I aware, this behaviour is
fixed (in that it looks for an sa in a directory named after the
culture of which the current thread is set to) - however, if it is not
fixed, or if I am able to customise it, then I would appreciate knowing
how :)

Thanks again,

-David
 
David said:
I appreciate the response, unfortunatly loading resource files through
ResourceReader isn't my problem:

My problem is that I wish to customise the manner in which the
ResourceManager class loads it's Satellite Assemblies for
localisation, as (for reason beyond this post) I have to use it for
my localisation resource handling. Currently, as far as I aware, this
behaviour is fixed (in that it looks for an sa in a directory named
after the culture of which the current thread is set to) - however,
if it is not fixed, or if I am able to customise it, then I would
appreciate knowing how :)

Well, yes, the search path is fixed in ResourceManager, but you can
write your own that searches a different path.

Remember that satellites are not *real* assemblies, they are not loaded
by Fusion, and IMO they should not have been called 'assemblies'. You
can load them using one of the Assembly Load methods then use
GetManifestResourceStream. What could be more simple?

Richard
 
Thanks Richard, I just wanted some sort of confirmiation that it was
fixed. Loading them myself isn't such a problem, it was just annoying
that the loading scheme in the manager was hardcoded!

Thanks again.
 
Back
Top