-1

クラスのインスタンスを動的にロードして、要件を使用してさまざまな基本型にキャストする必要があります。いくつかの例を読んで試してみると、実行時にクラスを操作するときに必要なすべてを理解していない可能性があることがわかりました。

抽象クラス B がインターフェイス A を実装している状況があります。現在、クラス B はクラス C の基本クラスです。実行時に、3 つの型すべてを含むアセンブリを動的にロードすると、Load を使用してできるはずです。コンテキストから、アセンブリをロードし、クラス C のインスタンスを作成し、それをインターフェイス A の型にキャストします。前もって感謝します。

http://msdn.microsoft.com/en-us/library/2xkww633.aspx

http://msdn.microsoft.com/en-us/library/1009fa28.aspx

public interface ICaseOutputGenerator
{
    String SampleProperty { get; set; }
    void Process();

}

public abstract class CaseOutputGeneratorBase : ICaseOutputGenerator
{
    public String SecondSampleProperty { get; set; }


    public virtual void SecondProcessMethod()
    {
    }

    public abstract void ThirdSampleProcessMethod();


    public string SampleProperty
    {
        get;
        set;
    }

    public void Process()
    {
        Console.WriteLine("Process in CaseOutputGeneratorBase Called");
    }
}

public class TestCaseOutputGenerator : CaseOutputGeneratorBase
{
    public override void ThirdSampleProcessMethod()
    {
        throw new NotImplementedException();
    }
}


//////////////////////////////////////////////////////////////////////////////

public class TestSandBoxManager {

    public TestSandBoxManager()
    {


    }

    public String ProcessAssemblyByFullDisplayName(String assemblyFullDisplayName)
    {
        String temp = String.Empty;
        var casecust = GetAssemblyByFullDisplayName(assemblyFullDisplayName);
        if (casecust != null)
            temp = ("Cast Passed");
        else
            temp = ("Cast Failed");

        return temp;

    }


    public String ProcessFile(String assemblyName, String className)
    {
        String temp = String.Empty;
        var casecust = GetCaseOutputGeneratorObject(assemblyName, className);
        if (casecust != null)
            temp=("Cast Passed");
        else
            temp=("Cast Failed");

        return temp;

    }

    private static object GetAssemblyByFullDisplayName(string fullName)
    {
        try
        {
            Type caseOutputGen = null;
            String fullQualifiedName = String.Empty;
            var localAssembly = Assembly.LoadFrom(fullName);

            foreach (var testType in localAssembly.GetTypes())
            {

                if ( testType.FullName != fullName)
                    continue; 
                fullQualifiedName = testType.FullName;
                break;
            }
            if (fullQualifiedName == null)
                return null;

            var obj = Activator.CreateInstance(Type.GetType(fullQualifiedName));
            return obj;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }



    public String ProcessFile2(String assemblyName, String className)
    {
        String temp = String.Empty;
        var casecust = GetCaseOutputGeneratorObjectLoadFrom(assemblyName, className);
        if (casecust != null)
            temp = ("Cast Passed");
        else
            temp = ("Cast Failed");

        return temp;

    }

    public static ICaseOutputGenerator GetCaseOutputGeneratorObject(string assemblyName, string className)
    {
        ICaseOutputGenerator caseOutputGen = null;

        var obj = GetObject(assemblyName, className);
        if (obj != null)
            caseOutputGen = (ICaseOutputGenerator)obj; // FAILS HERE
        return caseOutputGen;
    }

    public static ICaseOutputGenerator GetCaseOutputGeneratorObjectLoadFrom(string assemblyName, string className)
    {
        ICaseOutputGenerator caseOutputGen = null;

        try
        {
            var obj = GetObject2(assemblyName, className);
            if (obj != null)
                caseOutputGen = (ICaseOutputGenerator)obj; // FAILS HERE
        }
        catch (Exception ex)
        { 
            throw ex;
        }
        return caseOutputGen; 
    }

    private static object GetObject2(string fullName, string className)
    {
        try
        {
            Type caseOutputGen = null;
            String fullQualifiedName = String.Empty;
            var localAssembly = Assembly.LoadFrom(fullName);

            foreach (var testType in localAssembly.GetTypes())
            {

                if (!testType.FullName.EndsWith(className, StringComparison.InvariantCultureIgnoreCase)) 
                continue;
                caseOutputGen = testType;
                fullQualifiedName = testType.FullName;
                break;
            }
            if (caseOutputGen == null) 
                return null;

            var obj = Activator.CreateInstanceFrom(fullName, fullQualifiedName);
            return obj.Unwrap();
        } 
        catch (Exception ex)
        {
            throw ex;
        }
    }


    private static object GetObject(string fullName, string className)
    {
        try
        {
            Type caseOutputGen = null;
            var localAssembly = Assembly.LoadFrom(fullName);
            foreach (var testType in localAssembly.GetTypes())
            {
                if (!testType.FullName.EndsWith(className, StringComparison.InvariantCultureIgnoreCase)) continue;
                caseOutputGen = testType;
                break;
            }
            if (caseOutputGen == null) return null;

            var obj = Activator.CreateInstance(caseOutputGen);
            return obj;
        }
        catch (FileNotFoundException ex)
        {
            throw new Exception("Failed to load assembly: " + Environment.NewLine + fullName, ex);
        }
        catch (Exception ex)
        {
            throw new Exception("Failed to load assembly: " + Environment.NewLine + fullName, ex);
        }
    }
}

//////////////////////////////////////////////////////////////////////////////

public Boolean testReflection2()
    {
        try
        {
            //create an instance of the testsandboxmanager
            TestSandBoxManager t = new TestSandBoxManager();
            String ret = t.ProcessFile2(@"...\Documents\visual studio 2012\Projects\TestSandBox\TestSandBox\bin\Debug\TestSandBox.dll", "TestCaseOutputGenerator");
            Console.WriteLine(ret);
            Console.ReadLine();

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

これまでの質問を理解している人を助けるための私の解決策のイメージ

4

2 に答える 2

2

ほとんどの場合ICaseOutputGenerator、各アセンブリに 2 つずつあります。コードが同一であっても、オブジェクト/インターフェイスを別のアセンブリの同様の名前のインターフェイスにキャストすることはできません。ICaseOutputGeneratorデバッガーで作成されたオブジェクトを調べると、作成オブジェクトが独自のアセンブリから実装されていることを確認できます。

その場合は、ICaseOutputGenerator「カスタム ロード アセンブリ」とメイン アプリケーションの両方で同じアセンブリからインターフェイスを配置する場所を特定する必要があります。多くの場合、共有インターフェイスは個別のアセンブリに実装され、すべての「プラグイン」アセンブリとアプリケーション アセンブリにリンクされます。

于 2013-02-26T02:54:44.690 に答える
1

アレクセイ・レベンコフは的を射ていると思います。TestSandBox.dll を 2 回ロードします。プロジェクトへの参照として 1 回、Assembly.LoadFrom 経由で 2 回目。ドキュメントによると、これを自分でリンクすると、予期しない動作が発生する可能性があります。ここにあなたの参照のための引用があります:

アセンブリが LoadFrom で読み込まれ、プローブ パスに ID は同じで場所が異なるアセンブリが含まれている場合、InvalidCastException、MissingMethodException、またはその他の予期しない動作が発生する可能性があります。

これはまさにあなたの場合に起こっていることです。アセンブリの読み込み元のパスを変更して、メインの実行可能ファイルと同じフォルダーを指すようにすると、正常に機能します。

于 2013-02-27T02:04:43.423 に答える