tags:

views:

63

answers:

2

I want to know if I can tell what appdomain a object was created in. This is for a unit test but also useful general knowledge. I have the following pieces of code (this is example code for illustration).

public Foo Create()
{
    AppDomainSetup appDomainSetup = 
        new AppDomainSet { ApplicationBase = @"z:\SomePath" }

    AppDomain appDomain = 
                  AppDomain.CreateDomain("DomainName", null, appDomainSetup);

    return (Foo) appDomain.CreateInstanceAndUnwrap("MyAssembly", "MyClass");
}

I then call

Foo myFoo = Create();

What I would like to be able to do is find out what AppDomain method on myFoo will be called in, to test that the Create method had actually created a new AppDomain. I realise that I can add a method on Foo like

public class Foo
{
    public string appDomainName 
    { 
        get { return AppDomain.CurrentDomain.FriendlyName; } 
    }
}

This would provide me the appdomain that Foo is running in. I don't think this is an elegant solution just for a unit test. It would be great if someone could help define a method like.

public string GetAppDomainNameWithDotNetWitchcraft(Foo myFoo)
{
    // Insert voodoo here.
}

EDIT: Thanks for the responses and comments. The question I have asked has been answered and the comments have helped me realised where I was going wrong. What I really was trying to achieve is to test that a new AppDomain is created.

A: 

You should determine the AppDomain name in the constructor, as follows:

[Serializable]
public class Foo
{
    private string appDomainName;

    public Foo()
    {
         appDomainName = AppDomain.CurrentDomain.FriendlyName;
    }

    public string AppDomainName 
    { 
        get { return this.appDomainName; } 
    }
}

The default constructor will not run when your object is deserialized, so this way the string is serialized to the other AppDomain.

Steven
My example of exposing the name was just showing I realise how I could do get the appdomain, but I think it is a poor design as Foo doesn't care what app domain it is in. This is for a test so I don't like adding code specifically for test. (I don't mind designing for tests though)
btlog
+3  A: 

Well, you can do a bit of Spelunking via Remoting/Reflection, assuming your running in full trust. Note that you have to access a private property, and this assumes that the only thing it can find is remoting due to cross app domains:

    var a = Create();
    if (System.Runtime.Remoting.RemotingServices.IsTransparentProxy(a))
    {
        var c = System.Runtime.Remoting.RemotingServices.GetObjRefForProxy(a);
        var ad = c.ChannelInfo.ChannelData[0];
        var propDomainId = ad.GetType().GetProperty("DomainID", BindingFlags.NonPublic | BindingFlags.Instance);
        var DomainID = propDomainId.GetValue(ad,null);
    }

You can then compare that domain ID to your own to know if it's in your domain. Mind you, it's unlikely you'll enter the if statement if it is in your domain (trying to think of circumstances where you'd have a transparent proxy to an object in your own domain).

Damien_The_Unbeliever
Interesting. I didn't think of that.
Brian Rasmussen
I don't mind a bit of spelunking. That is useful. Although if I saw that in a unit test it does have a design smell :)
btlog
@btlog - I'm curious how fathoming whether an object is in a different AppDomain is a design smell, but writing a unit test to ensure it is isn't (if you get my meaning)?
Damien_The_Unbeliever
@Damien.. You are right. See my edit to the question. You have all helped me reaslise where I was going wrong.
btlog