10

なぜ私がこれをしたいのかについての簡単な説明:

Autodesk Revit Architecture 2010 のプラグインを作成するのに忙しいです。デバッグ セッションごとに Autodesk を再起動し、Revit プロジェクトを手動でロードし、[アドイン]タブをクリックしてプラグインを起動する必要があるため、プラグイン コードのテストは非常に面倒です。これには時間がかかりすぎます。

IronPython インタープリターをホストする 2 つ目のプラグインを作成しました。このようにして、Revit が提供する API をいじることができます。しかし最終的には、コードを C# で書き直してデバッグする必要があります。

簡単だと思いました。IronPython スクリプトからプラグイン DLL をロードして実行するだけです。これは機能しますが、DLL が Revit AppDomain に読み込まれるようになったため、読み込まれると Visual Studio で再コンパイルできません。

簡単だと思いました (StackOverflow の助けを借りて): DLL を新しい AppDomain にロードするだけです。残念ながら、RevitAPI オブジェクトは拡張されないため、別の AppDomain にマーシャリングすることはできませんMarshalByRefObject

私はシャドウコピーで何かに乗っているかもしれないと思います。ASP.NET がこれを行っているようです。しかし、MSDN のドキュメントを読むと、AppDomainを作成するときにしか指定できないようです。

現在の (既定の) AppDomain に対してこれを変更できますか? 特定のディレクトリから DLL のシャドウ コピーを使用するように強制できますか?

4

3 に答える 3

6

何をしようとしているのかわかりませんが、現在の AppDomain で ShadowCopy を有効にする非推奨の方法がいくつかあります。

AppDomain.CurrentDomain.SetCachePath(@"C:\Cache");
AppDomain.CurrentDomain.SetShadowCopyPath(AppDomain.CurrentDomain.BaseDirectory);
AppDomain.CurrentDomain.SetShadowCopyFiles();
于 2009-09-03T13:09:14.980 に答える
3

Main() メソッド コードを変更できない場合があります。たとえば、プラグインを作成していて、マネージャーによってインスタンス化されている場合などです。

その場合、アセンブリと pdb (および AssemblyResolve イベントの依存関係) を一時的な場所にコピーし、そこから Assembly.LoadFile() (LoadFrom() ではない) でロードすることをお勧めします。

長所: - dll のロックがありません。- ターゲット アセンブリが再コンパイルされるたびに、新しいバージョンにアクセスできます (これが .LoadFile() の理由です)。- アセンブリ全体が AppDomain.CurrentDomain で完全に利用可能です。

短所: - ファイルのコピーが必要です。- アセンブリをアンロードできず、リソースが解放されないため、不便になる可能性があります。

よろしく、

PD: このコードは機能します。

/// <summary>
/// Loads an assembly without locking the file
/// Note: the assemblys are loaded in current domain, so they are not unloaded by this class
/// </summary>
public class AssemblyLoader : IDisposable
{
    private string _assemblyLocation;
    private string _workingDirectory;
    private bool _resolveEventAssigned = false;

    /// <summary>
    /// Creates a copy in a new temp directory and loads the copied assembly and pdb (if existent) and the same for referenced ones. 
    /// Does not lock the given assembly nor pdb and always returns new assembly if recopiled.
    /// Note: uses Assembly.LoadFile()
    /// </summary>
    /// <param name="assemblyOriginalPath"></param>
    /// <returns></returns>
    public Assembly LoadFileCopy(string assemblyLocation)
    {
        lock (this)
        {
            _assemblyLocation = assemblyLocation;

            if (!_resolveEventAssigned)
            {
                _resolveEventAssigned = true;

                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyFileCopyResolveEvent);
            }

            //  Create new temp directory
            _workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            Directory.CreateDirectory(_workingDirectory);

            //  Generate copy
            string assemblyCopyPath = Path.Combine(_workingDirectory, Path.GetFileName(_assemblyLocation));
            System.IO.File.Copy(_assemblyLocation, assemblyCopyPath, true);

            //  Generate copy of referenced assembly debug info (if existent)
            string assemblyPdbPath = _assemblyLocation.Replace(".dll", ".pdb");
            if (File.Exists(assemblyPdbPath))
            {
                string assemblyPdbCopyPath = Path.Combine(_workingDirectory, Path.GetFileName(assemblyPdbPath));
                System.IO.File.Copy(assemblyPdbPath, assemblyPdbCopyPath, true);
            }

            //  Use LoadFile and not LoadFrom. LoadFile allows to load multiple copies of the same assembly
            return Assembly.LoadFile(assemblyCopyPath);
        }
    }

    /// <summary>
    /// Creates a new copy of the assembly to resolve and loads it
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    private Assembly AssemblyFileCopyResolveEvent(object sender, ResolveEventArgs args)
    {
        string referencedAssemblyFileNameWithoutExtension = System.IO.Path.GetFileName(args.Name.Split(',')[0]);

        //  Generate copy of referenced assembly
        string referencedAssemblyPath = Path.Combine(Path.GetDirectoryName(_assemblyLocation), referencedAssemblyFileNameWithoutExtension + ".dll");
        string referencedAssemblyCopyPath = Path.Combine(Path.GetDirectoryName(args.RequestingAssembly.Location), referencedAssemblyFileNameWithoutExtension + ".dll");
        System.IO.File.Copy(referencedAssemblyPath, referencedAssemblyCopyPath, true);

        //  Generate copy of referenced assembly debug info (if existent)
        string referencedAssemblyPdbPath = Path.Combine(Path.GetDirectoryName(_assemblyLocation), referencedAssemblyFileNameWithoutExtension + ".pdb");
        if (File.Exists(referencedAssemblyPdbPath))
        {
            string referencedAssemblyPdbCopyPath = Path.Combine(Path.GetDirectoryName(args.RequestingAssembly.Location), referencedAssemblyFileNameWithoutExtension + ".pdb");
            System.IO.File.Copy(referencedAssemblyPath, referencedAssemblyCopyPath, true);
        }

        //  Use LoadFile and not LoadFrom. LoadFile allows to load multiple copies of the same assembly
        return Assembly.LoadFile(referencedAssemblyCopyPath);
    }


    public void Dispose()
    {
        Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_resolveEventAssigned)
            {
                AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(AssemblyFileCopyResolveEvent);

                _resolveEventAssigned = false;
            }
        }
    }
}
于 2010-08-21T22:18:52.863 に答える
1

Revit プロジェクトを再度開かなくても変更、再コンパイル、テストできるように、他の Revit プラグインを動的にロード/アンロードするための Revit プラグインが追加されました。Building Coder ブログで見つけました。Revit SDK に付属しています。

于 2012-12-07T18:51:11.933 に答える