0

Importer と Processor で構成されるアプリケーションを作成しています。Importer は型を取り、その型の をインスタンス化しますList<>。プロセッサは、返されたリストを取得する必要があります。

たとえば、呼び出しImporter<Organisation>.GetObjects()て を返したいとしますList<Organisation>。次に、List を OrganizationProcessor に渡します。

Importer<Address>.GetObjects()同様に、呼び出して を返したいと思いList<Address>ます。次に、List を AddressProcessor に渡します。

Importer<>and *Processorの作成をファクトリに入れたいと考えています。すべてのコードを削除し、汚染されていないサンプルを以下に作成しました。私の試みは成功せず、私が完全に理解していない分散などのトピックにかかっている可能性があります。

class Program
{
    static void Main(string[] args)
    {
        //What I am currently doing
        Importer<Organisation> importer = new Importer<Organisation>();
        List<Organisation> list = importer.GetObjects();
        OrganisationProcessor processor = new OrganisationProcessor();
        processor.Process(list);


        //***What I want to do*** 
        string name = "Organisation";  //Passed in from external source
        var importer = Factory.GetImporter(name);  //returns Importer<Organisation>
        var processor = Factory.GetProcessor(name); //returns OrganisationProcessor
        processor.Process(importer.GetObjects()); //.Process takes List<Organisation>
    }
}

public class Importer<T>
{
    public List<T> GetObjects()
    {
        return new List<T>();
    }
}


public class OrganisationProcessor
{
    public void Process(List<Organisation> objects)
    {
        //Do something
    }
}

public class AddressProcessor
{
    public void Process(List<Address> objects)
    {
        //Do something
    }
}

public class Organisation { }

public class Address { }
4

4 に答える 4

2

これでうまくいくはずです。最初の意図が変更されていないことに注意してください。これは私にとっても驚きです。また、Factory で型リテラルに名前空間を追加する必要があることにも注意してください。LINQ を使用して型を検索する方が柔軟ですが、型へのパスと名前空間を 1 行で入力する方が読みやすいです。名前空間のないプロジェクトでこのサンプルを実行しましたが、問題なく動作しました。

void Main()
{
    string name = "Organisation";  //Passed in from external source
    var importer = Factory.GetImporter(name);  //returns Importer<Organisation>
    var processor = Factory.GetProcessor(name); //returns OrganisationProcessor
    processor.Process(importer.GetObjects()); //.Process takes List<Organisation>
    Console.WriteLine (importer.GetObjects().GetType());
}

public static class Factory
{
    public static Importer GetImporter(string name)
    {           
            //add namespace to name here
        var desiredType = Type.GetType(name);

        return new Importer(desiredType);
    }
    public static Processor GetProcessor(string name)
    {
            //add namespace to name here
        var desiredType = Type.GetType(name+"Processor");

        return (Processor)Activator.CreateInstance(desiredType);
    }
}

public class Importer 
{
    Type _typeOfEntities;

    public Importer(Type typeOfEntities)
    {
        _typeOfEntities = typeOfEntities;
    }
    public IList GetObjects()
    {
        Type generic = typeof(List<>);

        Type constructed = generic.MakeGenericType(new Type[] {_typeOfEntities});

        return (IList)Activator.CreateInstance(constructed);
    }
}
public interface Processor
{
    void Process(IList objects);
}

public class OrganisationProcessor : Processor
{
    public void Process(IList objects)
    {
        var desiredTypedObject = objects as List<Organisation>;
        if(desiredTypedObject != null)
        ProcessImp(desiredTypedObject);
    }
    private void ProcessImp(List<Organisation> objects)
    {
        Console.WriteLine ("processing Organisation");
    }
}

public class AddressProcessor
{
    public void Process(List<Address> objects)
    {
        //Do something by analogy
    }
}

public class Organisation { }

public class Address { }
于 2012-08-22T08:13:48.210 に答える
1

との戻りタイプはである必要がありGetImporterます。これらのメソッドに文字列の実行時情報を使用させ、コンパイル時に型がわかっているオブジェクトを返す方法はありません。GetProcessorobject

サンプルは次のようになります。

string name = "Organisation";  //Passed in from external source
dynamic importer = Factory.GetImporter(name);  //returns Importer<Organisation>
dynamic processor = Factory.GetProcessor(name); //returns OrganisationProcessor
processor.Process(importer.GetObjects()); //.Process takes List<Organisation>

次に、GetImporterメソッドは次のようになります。

public static object GetImporter(string name)
{
    Type type = Type.GetType(name);
    Type importerType = typeof(Importer<>).MakeGenericType(type);
    return Activator.CreateInstance(importerType);
}

最後に、GetProcessorは次のようになります

public static object GetProcessor(string name)
{
    Type type = Type.GetType(name + "Processor");
    return Activator.CreateInstance(type);
}

渡される文字列名は、名前空間を含む型のフルネームである必要があり、これは、これらのメソッドと同じアセンブリ内にある型(Organization、Address)に制限されることに注意してください。他のアセンブリで型を使用する場合は、アセンブリの修飾名を使用する必要がありますが、その場合、プロセッサ型の名前を生成するための文字列連結は機能しません。

おそらく、プロセッサタイプでカスタム属性を使用してから、上記のタイプ名を生成するための単純な文字列連結ではなく、カスタム属性を使用してアセンブリ内のすべてのタイプを検索します。上記のスキームは脆弱であり、一部のタイプの名前が変更されると簡単に壊れてしまう可能性があります。

于 2012-08-22T08:09:02.747 に答える
1

はい、可能です。クラスが同じアセンブリ内にあると仮定すると、以下のこのコードはあまり最適化されていませんが、問題は解決します。

public static class Factory
{
    public static object GetImporter(string name)
    {
        var assembly = Assembly.GetExecutingAssembly();

        var type = assembly.GetTypes().Single(t => t.Name.Equals(name));
        var importType = typeof (Importer<>).MakeGenericType(type);

        return Activator.CreateInstance(importType);

    }

    public static object GetProcessor(string name)
    {
        var assembly = Assembly.GetExecutingAssembly();
        var type = assembly.GetTypes()
               .Single(t => t.Name.Equals(string.Format("{0}Processor", name)));

        return Activator.CreateInstance(type);
    }
}

したがって、以下のように上記のFactoryを使用します。

dynamic importer = Factory.GetImporter(name);
dynamic processor = Factory.GetProcessor(name);
processor.Process(importer.GetObjects());
于 2012-08-22T08:10:54.470 に答える
0

ファクトリ内で Get... メソッドはActivator.CreateInstance Methodを使用できます。このメソッドは、追加のパラメーターを使用して assamby-name と type-name によってクラスのインスタンスを作成できます。

于 2012-08-22T07:41:27.903 に答える