Question

In my application I'm creating sandbox domain and I need dynamically define binding redirect rules. However I cannot pass neither ConfigurationFile setting nor raw xml data using SetConfigurationBytes method.

I created a sample to check if configuration data is applied to child domain:

var configData =
@"<?xml version='1.0' encoding='utf-8' ?>
<configuration>
  <appSettings>
    <add key='MyData' value='CUSTOM'/>
  </appSettings>
</configuration>";
var setup = new AppDomainSetup {
ApplicationBase = runtimeAssembliesPath // ,ConfigurationFile = configFilePath
                };
setup.SetConfigurationBytes(Encoding.UTF8.GetBytes(configData));
var sandbox = AppDomain.CreateDomain("Sandbox", evidence, setup);
var verifier = (Sample)_sandbox.CreateInstanceAndUnwrap(thisAssemblyName, typeof(Sample).FullName);
verifier.DebugPrint();

where Verifier is plain class with one method:

public class Sample: MarshalByRefObject 
{
    public void DebugPrint()
    {
        Debug.WriteLine("=====================================");
        Debug.Print("Reading config: =====|{0}|=====", ConfigurationManager.AppSettings["MyData"]);
        Debug.WriteLine("=====================================");
    }
}

Update The first issue with code above is that it must be inherited from MarshalByRefObject to marshal DebugPrint call to child appdomain instead of making call on copy created in current domain (thanks sthotakura). As a result ConfigurationFile setting begins to work.However still no luck with SetConfigurationBytes. Anyway the goal was to define bindingRules which DOES work if passed via SetConfigurationBytes.

Was it helpful?

Solution

To access an object across AppDomain boundary, the class must be derived from MarshalByRefObject.

From MSDN Page:

Types must inherit from MarshalByRefObject when the type is used across application domain boundaries, and the state of the object must not be copied because the members of the object are not usable outside the application domain where they were created.

That means, your Sample Class should derive from MarshalByRefObject:

[Serializable]
public class Sample : MarshalByRefObject
{
    public void DebugPrint()
    {
        Console.WriteLine("=====================================");
        Console.WriteLine(ConfigurationManager.AppSettings.Count);
        Console.WriteLine("Reading config: =====|{0}|=====", ConfigurationManager.AppSettings["MyData"]);
        Console.WriteLine("=====================================");
    }
}

I have tried in a sample app, but with a Config XML instead of calling SetConfigurationData and it works, Below is my Sample code for your reference:

var setup = new AppDomainSetup();
setup.ConfigurationFile = "SandBoxConfig.xml";
var sandbox = AppDomain.CreateDomain("Sandbox", null, setup);
var verifier = (Sample)sandbox.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Sample).FullName);
verifier.DebugPrint();

EDIT

From MSDN Page, AppDomainSetup.SetConfigurationBytes Method

Some consumers of configuration file information do not use the information stored by the SetConfigurationBytes method. The runtime does not enforce this. To ensure that all configuration file information is replaced in a new application domain, use the ConfigurationFile property to specify a configuration file. The SetConfigurationBytes method does affect assembly binding.

So, I suspect, types in System.Configuration namespace (like ConfigurationManager) ignoring the configuration data provided via SetConfigurationBytes.

OTHER TIPS

SetConfigurationBytes does work. I constructed an XDocument to represent the App.Config, as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="TestProbingPath" />
</assemblyBinding>
</runtime>
</configuration>

XDocument doc=as above
MemoryStream stream = new MemoryStream();
doc.Save(stream);
byte[] configBytes = stream.ToArray();

Note that stream.GetBuffer will not work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top