问题描述:

I'm developing an Azure Worker Role that will need to periodically perform actions based on work pulled from a WCF service. Due to the nature of Azure deployments, a decision was made to implement a plugin framework in Azure to allow quick updates to our product while minimizing the downtime by removing the need for full azure deployments, as well as supporting multiple versions of various assemblies.

A plugin is downloaded from Cloud storage and loaded into a class that contains all relevant info needed to load the assembly. (See PluginAssemblyInfo below)

In other development work I've developed the below ReflectionHelper class. This class works in other applications and I've verified it works in a console application.

However when running in the Azure emulator I get the following error: (I've added a comment on the line the exception is being thrown on.)

Type is not resolved for member 'MyCompanyName.ReflectionHelper,MyCompanyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

The ReflectionHelper class is added as a source file to the same assembly that is calling it. (I did edit the name of the assembly/namespaces for anonymity reasons)

Given the knowledge that this class works in other cases, my only guess is that it may be a trust issue, but I've not found much info online relating to this. Any help would be greatly appreciated.

This is the code for the ReflectionHelper class.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

using System.Runtime.Remoting;

using System.Runtime.Serialization;

using System.Web;

namespace MyCompanyName

{

[Serializable]

public class ReflectionHelper

{

public AppDomain appDomain { get; set; }

public byte[] PluginBytes { get; set; }

public string PluginClassName { get; set; }

public string PluginAssemblyName { get; set; }

public Dictionary<string, byte[]> AssemblyArchive { get; set; }

public object GetInstance(AppDomain NewDomain, byte[] PluginBytes, string PluginClassName, string PluginAssemblyName, Dictionary<string, byte[]> AssemblyArchive)

{

try

{

this.appDomain = NewDomain;

this.PluginBytes = PluginBytes;

this.PluginClassName = PluginClassName;

this.AssemblyArchive = AssemblyArchive;

this.PluginAssemblyName = PluginAssemblyName;

//this is the line that throws the serializationexception

appDomain.AssemblyResolve += new ResolveEventHandler((sender, args) =>

{

AssemblyName x = new AssemblyName(args.Name);

string Name = x.Name;

if (System.IO.Path.GetExtension(x.Name) != ".dll")

Name += ".dll";

Assembly Ret = appDomain.Load(this.AssemblyArchive[Name]);

return Ret;

});

appDomain.DoCallBack(LoaderCallBack);

return appDomain.GetData("Plugin");

}

catch (Exception ex)

{

throw ex;

}

}

public void LoaderCallBack()

{

ObjectHandle PluginObject = appDomain.CreateInstance(string.Format(this.PluginAssemblyName), PluginClassName);

appDomain.SetData("Plugin", PluginObject.Unwrap());

}

}

}

This is the code snippet that invokes it

AppDomain currentDomain = AppDomain.CurrentDomain;

AppDomainSetup domainSetup = new AppDomainSetup() { };

AppDomain BrokerJobDomain = AppDomain.CreateDomain("WorkerPluginDomain" + Guid.NewGuid().ToString());//, null, new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase });

ReflectionHelper helper = new ReflectionHelper();

object Instance = helper.GetInstance(BrokerJobDomain, pluginAssembly.PluginBytes, pluginAssembly.ClassName, pluginAssembly.AssemblyName, pluginAssembly.AssemblyArchive);

IWorkPlugin executor = (IWorkPlugin)Instance;

This is the assembly info class that is populated when the plugin is downloaded from cloud storage

public class PluginAssemblyInfo

{

public string ClassName { get; set; }

public byte[] PluginBytes { get; set; }

public Dictionary<string, byte[]> AssemblyArchive { get; set; }

public string AssemblyName { get; set; }

public DateTime LoadDate { get; set; }

}

网友答案:

The issue seems to be related to the RelativeSearchPath not being set up on the child domain. Ensuring the child domain had the same setup credentials seemed to fix this.

AppDomain currentDomain = AppDomain.CurrentDomain;
AppDomain BrokerJobDomain = AppDomain.CreateDomain("WorkerPluginDomain" + Guid.NewGuid().ToString(), null,  AppDomain.CurrentDomain.SetupInformation );
相关阅读:
Top