jeudi 13 août 2015

IIS Remote Exception

I have an IIS Application which references a plugin manager which reads all available plugins from a folder, when it is hosted after about 5-10 minutes I start getting the following Exception

[RemotingException: Object '/1608465e_9d80_4b40_be20_4c96904643e0/wizi+0g5od5gwmunm_indiws_253.rem' has been disconnected or does not exist at the server.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +14416170
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +388
PluginManager.Core.Interfaces.IPluggin.get_Id() +0
PluginManager.PluginDetails.get_Id() +27

I did some research and came accross ILease and ISponsor but I have no Idea how to implement it or how it works. My current code as it is at this moment, I just removed parts the body of the methods for clarity [Edit : added the method bodies]

public class AssemblyReflectionProxy : MarshalByRefObject
{
    private string _assemblyPath;

    public AssemblyReflectionProxy()
    {
        Id = "";
    }

    public void LoadAssembly(String assemblyPath)
    {
        try
        {
            _assemblyPath = assemblyPath;
            Assembly.ReflectionOnlyLoadFrom(assemblyPath);
        }
        catch (FileNotFoundException)
        {
        }
    }

    public TResult Reflect<TResult>(Func<Assembly, TResult> func)
    {
        var directory = new FileInfo(_assemblyPath).Directory;
        ResolveEventHandler resolveEventHandler = (s, e) => OnReflectionOnlyResolve(e, directory);
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += resolveEventHandler;
        var assembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(a => String.Compare(a.Location, _assemblyPath, StringComparison.Ordinal) == 0);
        var result = func(assembly);
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= resolveEventHandler;

        return result;
    }

    public T GetEntryType<T>()
    {
        var directory = new FileInfo(_assemblyPath).Directory;
        ResolveEventHandler resolveEventHandler = (s, e) => OnReflectionOnlyResolve(e, directory);
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += resolveEventHandler;
        var assembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(a => string.Compare(a.Location, _assemblyPath, StringComparison.Ordinal) == 0);
        if (assembly != null)
        {
            var result = assembly.GetTypes();
            var type = result.FirstOrDefault(x => x.GetInterface(typeof(T).Name) != null);
            if (type != null)
            {
                var remoteObject = AppDomain.CurrentDomain.CreateInstanceFrom(type.Assembly.Location, type.FullName);                   
                var obj = remoteObject.Unwrap();
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= resolveEventHandler;
                return (T)obj;
            }
        }
        return default(T);
    }

    private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
    {
        var loadedAssembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(asm => string.Equals(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase));

        if (loadedAssembly != null)
        {
            return loadedAssembly;
        }

        var assemblyName = new AssemblyName(args.Name);
        var dependentAssemblyFilename = Path.Combine(directory.FullName, assemblyName.Name + ".dll");

        if (File.Exists(dependentAssemblyFilename))
        {
            return Assembly.ReflectionOnlyLoadFrom(dependentAssemblyFilename);
        }
        return Assembly.ReflectionOnlyLoad(args.Name);
    }

    private string Id { get; set; }
    internal string GetId()
    {
        if (String.IsNullOrEmpty(Id))
        {
            var fileBytes = File.ReadAllBytes(_assemblyPath);
            var hash = Convert.ToBase64String(fileBytes).GetHashCode();
            var bytes = BitConverter.GetBytes(hash);
            StringBuilder sb = new StringBuilder();
            foreach (byte b in bytes)
                sb.Append(b.ToString("X2"));
            Id = sb.ToString();
        }
        return Id;
    }
}


public sealed class AssemblyManager : MarshalByRefObject, IDisposable
{
    private readonly Dictionary<string, AppDomain> _assemblyDomains = new Dictionary<string, AppDomain>();
    readonly Dictionary<string, AssemblyReflectionProxy> _proxies = new Dictionary<string, AssemblyReflectionProxy>();
    public AssemblyManager()
    {

    }

    public string LoadAssembly(string assemblyPath)
    {
        var fileInfo = new FileInfo(assemblyPath);
        var name = fileInfo.Name.Replace(".dll", "");
        if (fileInfo.Exists)
        {
            if (!_assemblyDomains.ContainsKey(name))
            {
                var appDomain = CreateChildDomain(AppDomain.CurrentDomain, fileInfo.Name);
                _assemblyDomains[name] = appDomain;
                try
                {
                    Type proxyType = typeof(AssemblyReflectionProxy);
                    {
                        var proxy = (AssemblyReflectionProxy)appDomain.CreateInstanceFrom(proxyType.Assembly.Location, proxyType.FullName).Unwrap();
                        proxy.LoadAssembly(assemblyPath);
                        _proxies[name] = proxy;
                        return name;
                    }
                }
                catch
                { }
            }
            else
            {
                return name;
            }
        }
        return "";
    }

    public void Unload()
    {

    }

    private AppDomain CreateChildDomain(AppDomain parentDomain, string domainName)
    {
        var evidence = new Evidence(parentDomain.Evidence);
        var setup = parentDomain.SetupInformation;
        return AppDomain.CreateDomain(domainName, evidence, setup);
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~AssemblyManager()
    {
        Dispose(false);
    }

    public IPluggin GetEntryPluggin(string name)
    {
        IPluggin plugin = default(IPluggin);
        if (_proxies.ContainsKey(name))
        {
            plugin = _proxies[name].GetEntryType<IPluggin>();
        }
        return plugin;
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            foreach (var appDomain in _assemblyDomains.Values)
                AppDomain.Unload(appDomain);
            _assemblyDomains.Clear();
        }
    }

    internal string GetEntryPlugginID(string name)
    {
        string Id = "";
        if (_proxies.ContainsKey(name))
        {
            Id = _proxies[name].GetId();
        }
        return Id;
    }
}

My Interface is

public interface IPluggin
{
    string Name { get; }
    string Version { get; }
    string Id { get; }
    void Initialize();
    string[] GetElements();
    void SaveSettings(string settings);
    void SetBasePath(string path);
}



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire