从程序集文件中获取自定义属性数据,然后解锁



程序集 A 声明在程序集 B 中应用的自定义程序集属性。

class MyAssemblyAttribute : Attribute { /* ... */ }

我需要从程序集 A 方法从程序集 B 获取该属性数据,而无需加载程序集 B。

程序集 A 中的伪代码:

var domain = AppDomain.Create();
MyAssemblyAttribute attr = null;
string path = "B.dll";
domain.DoCallback(() => {
       attr = Assembly.Load(path)
          .GetCustomAttributes()
          .OfType<MyAssemblyAttribute>()
          .First();
      });
AppDomain.Unload(domain);
File.Delete(path);
File.WriteAllBytes(path, ...);
return expectedAttr.Equals(attr);

我该怎么做?

我可以重新编译这两个程序集。我不能使用像Mono.Cecil或IKVM这样的第三方东西。

最后我做了这项工作:

var domain = AppDomain.CreateDomain(
    "CompiledAssemblyCheck",
    null,
    new AppDomainSetup()
    {
        LoaderOptimization = LoaderOptimization.MultiDomainHost,
        PrivateBinPath = Path.GetDirectoryName(Path.GetFullPath(otherAssembly)),
        ShadowCopyFiles = "true"
    });
try
{
    var data = File.ReadAllBytes(otherAssembly);
    string myPath = new Uri(executingAssembly.GetName().CodeBase).LocalPath;
    var proxy = (AssemblyAnyLoadProxy)domain.CreateInstanceFromAndUnwrap(myPath, typeof(AssemblyAnyLoadProxy).FullName);
    proxy.LoadFrom(myPath);
    int outputAssemblyId = proxy.Load(data);
    bool same = proxy.CompareAttribute(outputAssemblyId, typeof(MyAssemblyAttribute).FullName, expectedArgs);
}
finally
{
    AppDomain.Unload(domain);
}

    [Serializable]
    class AssemblyAnyLoadProxy : MarshalByRefObject
    {
        List<Assembly> _assemblies=new List<Assembly>();
        public int Load(byte[] raw)
        {
            Assembly asm = Assembly.ReflectionOnlyLoad(raw);
            return Add(asm);
        }
        public int LoadFrom(string assemblyFile)
        {
            Assembly asm = Assembly.ReflectionOnlyLoadFrom(assemblyFile);
            return Add(asm);
        }
        int Add(Assembly asm)
        {
            _assemblies.Add(asm);
            return _assemblies.Count - 1;
        }
        public bool CompareAttribute(int assembly, string fullName, object[] args)
        {
            var attrs = CustomAttributeData.GetCustomAttributes(_assemblies[assembly]);
            CustomAttributeData attr = attrs.FirstOrDefault(x => x.Constructor.DeclaringType.FullName == fullName);
            return attr?.ConstructorArguments.Select(x => x.Value).SequenceEqual(args) ?? false;
        }
    }

相关内容

  • 没有找到相关文章