Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在新AppDomain下执行dll程序集_C#_.net_.net Assembly_Appdomain - Fatal编程技术网

C# 在新AppDomain下执行dll程序集

C# 在新AppDomain下执行dll程序集,c#,.net,.net-assembly,appdomain,C#,.net,.net Assembly,Appdomain,我已经研究了几天了。我正在尝试在外部程序集中自己的AppDomain下正确创建类的实例 我已经能够在新的AppDomain下加载外部程序集,但是它的所有依赖项似乎都加载在父AppDomain中,这与此目的背道而驰,因为我想稍后卸载dll以释放它们上的锁(插件系统)。你知道为什么会这样做吗 public MyCustomObject BindAssembly() { string currentAssemblyPath = @"C:\PathToMy\Assembly"; stri

我已经研究了几天了。我正在尝试在外部程序集中自己的AppDomain下正确创建类的实例

我已经能够在新的AppDomain下加载外部程序集,但是它的所有依赖项似乎都加载在父AppDomain中,这与此目的背道而驰,因为我想稍后卸载dll以释放它们上的锁(插件系统)。你知道为什么会这样做吗

public MyCustomObject BindAssembly()
{
    string currentAssemblyPath = @"C:\PathToMy\Assembly";
    string currentAssemblyFile = @"C:\PathToMy\Assembly\MyAssembly.dll";
    AssemblyName currentAssemblyName = AssemblyName.GetAssemblyName(currentAssemblyFile);
    AppDomain domain = AppDomain.CurrentDomain;
    domain.AssemblyResolve += domain_AssemblyResolve;
    AppDomainSetup setup = new AppDomainSetup()
    {
        PrivateBinPath = currentAssemblyPath,
        ApplicationBase = domain.BaseDirectory,
        DynamicBase = domain.SetupInformation.DynamicBase,
        ShadowCopyFiles = domain.SetupInformation.ShadowCopyFiles,
        CachePath = domain.SetupInformation.CachePath,
        AppDomainManagerAssembly = domain.SetupInformation.AppDomainManagerAssembly,
        AppDomainManagerType = domain.SetupInformation.AppDomainManagerType
    };
    AppDomain newDomain = AppDomain.CreateDomain("NewDomain", AppDomain.CurrentDomain.Evidence, setup);
    newDomain.AssemblyResolve += newDomain_AssemblyResolve;

    currentAssembly = newDomain.Load(currentAssemblyName);
    // tried this too
    //var obj = domain.CreateInstanceFromAndUnwrap(currentAssemblyFile, className);

    // list all of the assemblies inside the custom app domain
    var newDomainAssemblies = newDomain.GetAssemblies(); // (contains my loaded assembly, but not dependencies)

    // list all of the assemblies inside the parent app domain
    var appAssemblies = AppDomain.CurrentDomain.GetAssemblies(); // (contains my loaded assembly as well as all dependencies)

    return obj as MyCustomObject;
}

// resolve dependencies in custom domain
Assembly newDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    // this never fires
    AppDomain domain = (AppDomain)sender;
}

// resolve dependencies in parent domain
Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    AppDomain domain = (AppDomain)sender;
    string assemblyDependencyPath = String.Format(@"{0}", Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(args.RequestingAssembly.CodeBase).Path)));
    string[] files = Directory.GetFiles(assemblyDependencyPath, "*.dll", SearchOption.AllDirectories);
    foreach (string file in files)
    {
        // if we found it, load the assembly and cache it.

        AssemblyName aname = AssemblyName.GetAssemblyName(file);
        if (aname.FullName.Equals(args.Name))
        {
            Assembly assembly = domain.Load(aname);
            //Assembly assembly = Assembly.LoadFrom(file);  // also tried this, same result
            return assembly;
        }
    }
}
我不确定这个(或者通常跨appdomain)将如何处理抽象类的不同实现,因为您可能会发现在主
appdomain
中使用子类仍然需要依赖项,但我最近不得不做类似的事情,并发现使用可序列化加载程序类,它与
MyCustomObject
位于同一程序集中,是保持事物独立的最佳方式

其思想是在当前的
AppDomain
中创建加载程序,然后将其编组到新的
AppDomain
,并要求加载和实例化所需的程序集和类型

请注意,加载程序和从
MyCustomObject
继承的任何内容都必须是或继承自,因为它们将在
AppDomain
之间传递

public MyCustomObject BindAssembly()
{
    string currentAssemblyPath = @"C:\PathToMy\Assembly";
    string currentAssemblyFile = @"C:\PathToMy\Assembly\MyAssembly.dll";
    AssemblyName currentAssemblyName = AssemblyName.GetAssemblyName(currentAssemblyFile);
    AppDomain domain = AppDomain.CurrentDomain;
    domain.AssemblyResolve += domain_AssemblyResolve;
    AppDomainSetup setup = new AppDomainSetup()
    {
        PrivateBinPath = currentAssemblyPath,
        ApplicationBase = domain.BaseDirectory,
        DynamicBase = domain.SetupInformation.DynamicBase,
        ShadowCopyFiles = domain.SetupInformation.ShadowCopyFiles,
        CachePath = domain.SetupInformation.CachePath,
        AppDomainManagerAssembly = domain.SetupInformation.AppDomainManagerAssembly,
        AppDomainManagerType = domain.SetupInformation.AppDomainManagerType
    };

    AppDomain newDomain = AppDomain.CreateDomain("NewDomain", AppDomain.CurrentDomain.Evidence, setup);

    newDomain.Load(typeof(Loader).Assembly.GetName());

    Loader loader = (Loader)newDomain.CreateInstanceAndUnwrap(
        typeof(Loader).Assembly.FullName, typeof(Loader).FullName);

    // load the assembly containing MyCustomObject into the remote domain
    loader.LoadAssembly(currentAssemblyFile);

    // ask the Loader to create the object instance for us
    MyCustomObject obj = loader.CreateCustomObject();

    return obj;
}

public class Loader : MarshalByRefObject
{
    /// <summary>Stores the assembly containing the task class.</summary>
    private Assembly assembly;

    /// <summary>Retrieves the current lifetime service object that controls the lifetime policy for this instance.</summary>
    /// <returns>This always returns null.</returns>
    public override object InitializeLifetimeService()
    {
        return null;
    }

    /// <summary>Loads the assembly containing the task class.</summary>
    /// <param name="path">The full path to the assembly DLL containing the task class.</param>
    public void LoadAssembly(string path)
    {
        this.assembly = Assembly.Load(AssemblyName.GetAssemblyName(path));
    }

    /// <summary>Instantiates the required object.</summary>
    /// <param name="classFullName">The full name (namespace + class name) of the task class.</param>
    /// <returns>The new object.</returns>
    public MyCustomObject CreateCustomObject()
    {
        MyCustomObject instance = new MyCustomObject();
        // do whatever you want with the instance here
        return instance;
    }
}
public MyCustomObject BindAssembly()
{
字符串currentAssemblyPath=@“C:\Pathomy\Assembly”;
字符串currentAssemblyFile=@“C:\Pathomy\Assembly\MyAssembly.dll”;
AssemblyName currentAssemblyName=AssemblyName.GetAssemblyName(currentAssemblyFile);
AppDomain域=AppDomain.CurrentDomain;
domain.AssemblyResolve+=域_AssemblyResolve;
AppDomainSetup=新建AppDomainSetup()
{
PrivateBinPath=currentAssemblyPath,
ApplicationBase=domain.BaseDirectory,
DynamicBase=domain.SetupInformation.DynamicBase,
ShadowCopyFiles=domain.SetupInformation.ShadowCopyFiles,
CachePath=domain.SetupInformation.CachePath,
AppDomainManagerAssembly=domain.SetupInformation.AppDomainManagerAssembly,
AppDomainManagerType=domain.SetupInformation.AppDomainManagerType
};
AppDomain newDomain=AppDomain.CreateDomain(“newDomain”,AppDomain.CurrentDomain.Evidence,setup);
Load(typeof(Loader.Assembly.GetName());
加载器加载器=(加载器)newDomain.CreateInstanceAndUnwrap(
typeof(Loader.Assembly.FullName,typeof(Loader.FullName);
//将包含MyCustomObject的程序集加载到远程域
loader.LoadAssembly(currentAssemblyFile);
//请加载程序为我们创建对象实例
MyCustomObject obj=loader.CreateCustomObject();
返回obj;
}
公共类装入器:MarshalByRefObject
{
///存储包含任务类的程序集。
私人集会;
///检索控制此实例的生存期策略的当前生存期服务对象。
///这总是返回null。
公共重写对象初始化ElifetimeService()
{
返回null;
}
///加载包含任务类的程序集。
///包含任务类的程序集DLL的完整路径。
公共void加载程序集(字符串路径)
{
this.assembly=assembly.Load(AssemblyName.GetAssemblyName(路径));
}
///实例化所需的对象。
///任务类的全名(命名空间+类名)。
///新对象。
公共MyCustomObject CreateCustomObject()
{
MyCustomObject实例=新建MyCustomObject();
//对这里的实例执行任何您想要的操作
返回实例;
}
}

您是否尝试过
currentAssembly=newDomain.Load(currentAssemblyName)而不是
currentAssembly=domain.Load(currentAssemblyName)?我还确认,如果卸载我创建的新AppDomain,依赖程序集仍然保留在父AppDomain中。Rhumboll-很抱歉,我的存根代码中有一个输入错误。修复了我的问题。您不能引用在AppDomain中加载的程序集中定义的任何类型。比如我的自定义对象。改用在另一个程序集中定义的接口。当你查询“.net plugin architecture”.Hans时,谷歌点击了很多次-MyCustomObject并没有在加载的程序集中定义,而是一个抽象类,它是在一个单独的抽象程序集中定义的,由双方共享。我使用代理尝试了类似的方法,然而,我修改了它以符合您的建议,但它在这里失败,出现了一个无法加载程序集错误:Loader Loader=(Loader)domain.createInstanceFromandWrap(typeof(Loader.assembly.FullName),typeof(Loader.FullName);经过一些修改后,我意识到我必须将CreateInstanceFromAndUnwrap()的完整路径传递给dll,但是依赖项添加到父AppDomain的行为仍然存在。