문제

나는 누군가가 메인 애플리케이션의 코드를 터치하지 않고 응용 프로그램에 대한 플러그인을 쓸 수 있도록 광산 응용 프로그램에 대한 확장 성을 제공하기 위해 플러그인 시스템을 작성하려고합니다.

기본 "iplugin"인터페이스가 작성되었습니다 (ATM, 아직 구현 된 것은 없습니다)

내가 로딩하는 방법은 다음과 같습니다.

public static void Load()
{
    // rawr: http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx
    String[] pluginFiles = Directory.GetFiles(Plugins.PluginsDirectory, "*.dll");
    foreach (var plugin in pluginFiles)
    {
        Type objType = null;
        try
        {
            //Assembly.GetExecutingAssembly().GetName().Name
            MessageBox.Show(Directory.GetCurrentDirectory());
            Assembly asm = Assembly.Load(plugin);
            if (asm != null)
            {
                objType = asm.GetType(asm.FullName);
                if (objType != null)
                {
                    if (typeof(IPlugin).IsAssignableFrom(objType))
                    {
                        MessageBox.Show(Directory.GetCurrentDirectory());
                        IPlugin ipi = (IPlugin)Activator.CreateInstance(objType);
                        ipi.Host = Plugins.m_PluginsHost;
                        ipi.Assembly = asm;
                    }
                }
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString(), "Unhandled Exception! (Please Report!)", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
        }
    }
}

친구가 도와 주려고 노력했지만 실제로 무엇이 잘못되었는지 이해하지 못했습니다.

플러그인의 폴더 구조는 다음과 같습니다.

\
플러그인

모든 플러그인은 [root] 디렉토리에 "lab.core.dll"이라는 .dll을 참조하고 중복 참조가로드 되었기 때문에 플러그인 디렉토리에 존재하지 않습니다.

플러그인 시스템은 실험실에서 참조되는 lab.core.dll에서로드됩니다. 유형 "iplugin"은 Lab.core.dll에도 있습니다. lab.core.dll은 정확히 내 응용 프로그램의 핵심입니다.

편집하다:

질문 : 왜/내가 얻는 예외는 무엇이며 어떻게 해결할 수 있습니까?

최종 편집 :

좋아, 그래서 나는 친구가 TF2 레귤레이터를 위해 쓴 소스 코드를보고 다시 작성하기로 결정했습니다.

여기에 내가 얻은 것과 효과가 있습니다.

    public class TestPlugin : IPlugin {
    #region Constructor

    public TestPlugin() {
        //
    }

    #endregion

    #region IPlugin Members

    public String Name {
        get {
            return "Test Plugin";
        }
    }

    public String Version {
        get {
            return "1.0.0";
        }
    }

    public String Author {
        get {
            return "Zack";
        }
    }

    public Boolean OnLoad() {
        MessageBox.Show("Loaded!");
        return true;
    }

    public Boolean OnAllLoaded() {
        MessageBox.Show("All loaded!");
        return true;
    }

    #endregion
}

        public static void Load(String file) {
        if (!File.Exists(file) || !file.EndsWith(".dll", true, null))
            return;

        Assembly asm = null;

        try {
            asm = Assembly.LoadFile(file);
        } catch (Exception) {
            // unable to load
            return;
        }

        Type pluginInfo = null;
        try {
            Type[] types = asm.GetTypes();
            Assembly core = AppDomain.CurrentDomain.GetAssemblies().Single(x => x.GetName().Name.Equals("Lab.Core"));
            Type type = core.GetType("Lab.Core.IPlugin");
            foreach (var t in types)
                if (type.IsAssignableFrom((Type)t)) {
                    pluginInfo = t;
                    break;
                }

            if (pluginInfo != null) {
                Object o = Activator.CreateInstance(pluginInfo);
                IPlugin plugin = (IPlugin)o;
                Plugins.Register(plugin);
            }
        } catch (Exception) {
        }
    }

    public static void LoadAll() {
        String[] files = Directory.GetFiles("./Plugins/", "*.dll");
        foreach (var s in files)
            Load(Path.Combine(Environment.CurrentDirectory, s));

        for (Int32 i = 0; i < Plugins.List.Count; ++i) {
            IPlugin p = Plugins.List.ElementAt(i);
            try {
                if (!p.OnAllLoaded()) {
                    Plugins.List.RemoveAt(i);
                    --i;
                }
            } catch (Exception) {
                Plugins.List.RemoveAt(i);
                --i;
            }
        }
    }
도움이 되었습니까?

해결책

원형 참조가있는 것 같습니다. 플러그인 참조 lab.core.dll이라고 말하지만 플러그인은 Lab.core.dll에서로드된다고합니다.

여기서 무슨 일이 일어나고 있는지 오해하고 있습니까?

편집 : 이제 질문에 질문을 추가 했으니 ...

Lab.core.dll이 종속성이므로 플러그인에 액세스 할 수 있어야합니다. 일반적으로 동일한 디렉토리 나 GAC에있는 것을 의미합니다.

나는 여기에 더 깊은 디자인 문제가 있다고 생각하지만 이것은 당신의 즉각적인 문제입니다.

다른 팁

MEF (Managed Extensibility Framework)는 .NET의 새로운 라이브러리로 응용 프로그램 및 구성 요소를 더 많이 재사용 할 수 있습니다. .NET 응용 프로그램은 MEF를 사용하여 정적으로 컴파일되는 것에서 동적으로 구성된 것으로 전환 할 수 있습니다. 확장 가능한 응용 프로그램, 확장 가능한 프레임 워크 및 응용 프로그램 확장을 구축하는 경우 MEF가 귀하를위한 것입니다.

http://www.codeplex.com/mef

편집 : CodePlex가 사라지고 있습니다 - 코드는 보관 목적으로 만 Github로 이동되었습니다. https://github.com/microsoftarchive/mef

부작용으로, 나는이 두 인터페이스를 사용하여이를 구현합니다.

///<summary>
///</summary>
public interface IPlugin {
    ///<summary>
    ///</summary>
    string Name { get; }
    ///<summary>
    ///</summary>
    string Description { get; }
    ///<summary>
    ///</summary>
    string Author { get; }
    ///<summary>
    ///</summary>
    string Version { get; }

    ///<summary>
    ///</summary>
    IPluginHost Host { get; set; }

    ///<summary>
    ///</summary>
    void Init();
    ///<summary>
    ///</summary>
    void Unload();

    ///<summary>
    ///</summary>
    ///<returns></returns>
    IDictionary<int, string> GetOptions();
    ///<summary>
    ///</summary>
    ///<param name="opcion"></param>
    void ExecuteOption(int option);

}



///<summary>
///</summary>
public interface IPluginHost {
    ///<summary>
    ///</summary>
    IDictionary<string, object> Variables { get; }
    ///<summary>
    ///</summary>
    ///<param name="plugin"></param>
    void Register(IPlugin plugin);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top