简体   繁体   English

从AppDomain获取静态列表

[英]Get static List from AppDomain

I want to get access to a static List of Class2, which will be created in Class1. 我想访问将在Class1中创建的Class2静态列表。

Class1 is loaded in an AppDomain and loads Class2 in an other AppDomain. Class1加载到一个AppDomain中,而Class2加载到另一个AppDomain中。 But if I want to get access to the static List in Class2, I get two different Lists. 但是,如果我想访问Class2中的静态列表,则会得到两个不同的列表。

I think I have to access to the same AppDomain in Class1 to get Class2, but how I can achieve this, if the objects of Class1 are in different AppDomains? 我想我必须访问Class1中的相同AppDomain才能获得Class2,但是如果Class1的对象位于不同的AppDomain中,我如何实现呢?

By the way: It is not neccessary to put Class2 in an other AppDomain, but I thought I could get the same object if I would do it. 顺便说一句:不必将Class2放在另一个AppDomain中,但是我认为如果可以的话,我可以得到相同的对象。

Here is my code: 这是我的代码:

public class Class1 : MarshalByRefObject
{
    Class2 class2;

    public Class2 Class2
    {
        get { return class2; }
        set { class2 = value; }
    }
    public Class1()
    {
        AppDomain adc2 = AppDomain.CreateDomain("adc2");
        class2 = (Class2)adc2.CreateInstanceAndUnwrap(typeof(Class2).Assembly.FullName, typeof(Class2).FullName);
    }
}
public class Class2 : MarshalByRefObject
{
    static List<int> myIntegers = new List<int>();

    public static List<int> MyIntegers
    {
        get { return Class2.myIntegers; }
        set { Class2.myIntegers = value; }
    }
    public void AddInteger(int integer)
    {
        myIntegers.Add(integer);
    }
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        foreach (int integer in myIntegers)
        {
            sb.AppendLine(integer.ToString());
        }
        return sb.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Type type1 = typeof(Class1);
        AppDomain ad1 = AppDomain.CreateDomain("ad1");
        Class1 ad1t1 = (Class1)ad1.CreateInstanceFromAndUnwrap(type1.Assembly.Location, type1.FullName);

        AppDomain ad2 = AppDomain.CreateDomain("ad2");
        Class1 ad2t1 = (Class1)ad2.CreateInstanceFromAndUnwrap(type1.Assembly.Location, type1.FullName);

        ad1t1.Class2.AddInteger(0);
        ad2t1.Class2.AddInteger(1);
        Console.WriteLine(ad1t1.Class2.ToString()); //Output: 0
        Console.WriteLine(ad2t1.Class2.ToString()); //Output: 1
        //
        Console.ReadKey();
    }
}

Edit 编辑

Ok I found out that my plugin loader is to blame. 好的,我发现是我的插件加载器惹的祸。 Can someone say why you cant work across appdomains if you will use different Pluginloaders (or at least one loader)? 有人可以说为什么如果您要使用不同的Pluginloader(或至少一个加载器),则无法跨应用程序域工作?

If all files are in one Assembly it will work (increment is 3). 如果所有文件都在一个程序集中,则它将起作用(增量为3)。 In my scenario (many different assemblies) I only get 1,1,1 在我的场景(许多不同的程序集)中,我只会得到1,1,1

If someone need more information to help me, feel free to ask for it. 如果有人需要更多信息来帮助我,请随时提出要求。

Example 1 (Each Instance count for itself): 示例1(每个实例本身的计数):

Assembly: Main 组装:主

PluginLoader.PluginLoader<IPlugin> pluginLoader1 = new PluginLoader.PluginLoader<IPlugin>(new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)));
IPlugin cl1 = pluginLoader1.Activate("MyLibrary.dll", "MyLibrary.Class1");
PluginLoader.PluginLoader<IPlugin> pluginLoader2 = new PluginLoader.PluginLoader<IPlugin>(new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)));
IPlugin cl3 = pluginLoader2.Activate("MyLibrary2.dll", "MyLibrary2.Class3");
//Increment() increases a static variable starting by 0
cl1.Increment();
Console.WriteLine(cl1.ToString()); //Output: 1
cl3.Increment();
Console.WriteLine(cl3.ToString()); //Output: 1

ClassLibrary2.Class2 class2 = new ClassLibrary2.Class2();
class2.Increment();
Console.WriteLine(class2.ToString()); //Output: 1

Assembly: ClassLibrary2 汇编:ClassLibrary2

[Serializable]
public class Class2 : IPlugin
{
    public Class2() { }

    public override string ToString()
    {
        return incrementer.ToString();
    }
    static int incrementer = 0;
    public void Increment()
    {
        incrementer++;
    }
}

Assembly: MyLibrary 汇编:MyLibrary

public class Class1 : MarshalByRefObject, IPlugin
{
    Class2 class2;

    public Class2 Class2
    {
        get { return class2; }
        set { class2 = value; }
    }
    public Class1()
    {
        PluginLoader.PluginLoader<Class2> pluginLoader = new PluginLoader.PluginLoader<Class2>(new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)));
        class2 = pluginLoader.Activate("ClassLibrary2.dll", "ClassLibrary2.Class2");
        //AppDomain adc2 = AppDomain.CreateDomain("adc2");
        //class2 = (Class2)adc2.CreateInstanceAndUnwrap(typeof(Class2).Assembly.FullName, typeof(Class2).FullName);
    }
    public void Increment()
    {
        this.class2.Increment();
    }
    public override string ToString()
    {
        return AppDomain.CurrentDomain.FriendlyName+": "+ this.class2.ToString();
    }
}

Assembly: MyLibrary2 程序集:MyLibrary2

public class Class3 : MarshalByRefObject, IPlugin
{
    Class2 class2;

    public Class2 Class2
    {
        get { return class2; }
        set { class2 = value; }
    }
    public Class3()
    {
        PluginLoader.PluginLoader<Class2> pluginLoader = new PluginLoader.PluginLoader<Class2>(new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)));
        class2 = pluginLoader.Activate("ClassLibrary2.dll", "ClassLibrary2.Class2");
        //AppDomain adc2 = AppDomain.CreateDomain("adc2");
        //class2 = (Class2)adc2.CreateInstanceAndUnwrap(typeof(Class2).Assembly.FullName, typeof(Class2).FullName);
    }
    public void Increment()
    {
        this.class2.Increment();
    }
    public override string ToString()
    {
        return AppDomain.CurrentDomain.FriendlyName + ": " + this.class2.ToString();
    }
}

Assembly: PluginInterface 组装:PluginInterface

public interface IPlugin
{
    void Increment();
}

Assembly: PluginLoader 组装:PluginLoader

public class PluginLoader<T> where T : IPlugin
{
    //Here are placed all Fields
    #region Fields
    string path;
    System.AppDomain appDomain;
    #endregion

    //Here are placed all Properties
    #region Properties
    public List<KeyValuePair<String, String>> Plugins
    {
        get { return (List<KeyValuePair<String, String>>)appDomain.GetData("Plugins"); }
    }
    #endregion

    //Here are placed all Constructors
    #region Constructors
    public PluginLoader(DirectoryInfo path)
    {
        this.path = path.FullName;
        if (!path.Exists)
            path.Create();
        AppDomainSetup appDomainSetup = new AppDomainSetup();
        appDomainSetup.AppDomainInitializer = new AppDomainInitializer(GetInterfaceTypes);
        appDomainSetup.AppDomainInitializerArguments = new string[] { this.path };
        appDomain = AppDomain.CreateDomain(typeof(T).Name, null, appDomainSetup);
    }
    #endregion

    #region Methods
    private static void GetInterfaceTypes(string[] args)
    {
        AppDomain appDomain = System.AppDomain.CurrentDomain;
        string[] files = Directory.GetFiles(args[0], "*.dll", SearchOption.AllDirectories);
        List<KeyValuePair<String, String>> infos = new List<KeyValuePair<String, String>>();
        foreach (string file in files)
        {
            try
            {
                Assembly asm = Assembly.LoadFrom(file);
                foreach (Type type in asm.GetTypes())
                {
                    if (typeof(T).IsAssignableFrom(type))
                        infos.Add(new KeyValuePair<string, string>(file, type.FullName));
                }
            }
            catch (Exception ex)
            {
            }
        }
        appDomain.SetData("Plugins", infos);
    }
    public virtual T Activate(String assemblyFile, String type, params object[] args)
    {
        try
        {
            T instance = (T)this.appDomain.CreateInstanceFromAndUnwrap(Path.Combine(this.path, Path.GetFileName(assemblyFile)), type, args);
            return instance;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    #endregion
}

Example 2 (Each instance count the same increment variable): 示例2(每个实例计数相同的增量变量):

Put all classes in one assembly. 将所有类放在一个程序集中。

public interface IPlugin
{
    void Increment();
}
[Serializable]
public class Class1 : IPlugin
{
    public Class1() { }
    static int incrementer = 0;
    public void Increment()
    {
        incrementer++;
    }
    public override string ToString()
    {
        return incrementer.ToString();
    }
}
class PluginLoader<T> where T : IPlugin
{
    //Here are placed all Fields
    #region Fields
    string path;
    System.AppDomain appDomain;
    #endregion

    //Here are placed all Properties
    #region Properties
    public List<KeyValuePair<String, String>> Plugins
    {
        get { return (List<KeyValuePair<String, String>>)appDomain.GetData("Plugins"); }
    }
    #endregion

    //Here are placed all Constructors
    #region Constructors
    public PluginLoader(DirectoryInfo path)
    {
        this.path = path.FullName;
        if (!path.Exists)
            path.Create();
        AppDomainSetup appDomainSetup = new AppDomainSetup();
        appDomainSetup.AppDomainInitializer = new AppDomainInitializer(GetInterfaceTypes);
        appDomainSetup.AppDomainInitializerArguments = new string[] { this.path };
        appDomain = AppDomain.CreateDomain(typeof(T).Name, null, appDomainSetup);
    }
    #endregion

    #region Methods
    private static void GetInterfaceTypes(string[] args)
    {
        AppDomain appDomain = System.AppDomain.CurrentDomain;
        string[] files = Directory.GetFiles(args[0], "*.dll", SearchOption.AllDirectories);
        List<KeyValuePair<String, String>> infos = new List<KeyValuePair<String, String>>();
        foreach (string file in files)
        {
            try
            {
                Assembly asm = Assembly.LoadFrom(file);
                foreach (Type type in asm.GetTypes())
                {
                    if (typeof(T).IsAssignableFrom(type))
                        infos.Add(new KeyValuePair<string, string>(file, type.FullName));
                }
            }
            catch (Exception ex)
            {
            }
        }
        appDomain.SetData("Plugins", infos);
    }
    public virtual T Activate(String assemblyFile, String type, params object[] args)
    {
        try
        {
            T instance = (T)this.appDomain.CreateInstanceFromAndUnwrap(Path.Combine(this.path, Path.GetFileName(assemblyFile)), type, args);
            return instance;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    #endregion
}
class Program
{
    static void Main(string[] args)
    {
        string file = System.Reflection.Assembly.GetExecutingAssembly().Location;
        string path = Path.GetDirectoryName(file);

        PluginLoader<IPlugin> pluginLoader1 = new PluginLoader<IPlugin>(new DirectoryInfo(path));
        IPlugin cl1 = pluginLoader1.Activate(file, "AppDomainCheck.Class1");
        PluginLoader<IPlugin> pluginLoader2 = new PluginLoader<IPlugin>(new DirectoryInfo(path));
        IPlugin cl3 = pluginLoader1.Activate(file, "AppDomainCheck.Class1");

        cl1.Increment();
        Console.WriteLine(cl1.ToString()); //Output: 1
        cl3.Increment();
        Console.WriteLine(cl3.ToString()); //Output: 2

        Console.ReadKey();
    }
}

Static variables are limited to the current App domain. 静态变量仅限于当前的App域。 If you have N different app domains, then you have N different values for a static property. 如果您有N个不同的应用程序域,则静态属性有N个不同的值。

In C# Language Specification 5.0 : C#语言规范5.0中

10.5.1 A static field is not part of a specific instance; 10.5.1静态字段不属于特定实例; instead, it is shared amongst all instances of a closed type (§4.4.2). 相反,它在所有封闭类型的实例之间共享(第4.4.2节)。 No matter how many instances of a closed class type are created, there is only ever one copy of a static field for the associated application domain . 无论创建了多少个封闭类类型的实例, 关联的应用程序域仅存在一个静态字段的副本

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM